diff options
-rw-r--r-- | include/linux/tracehook.h | 27 | ||||
-rw-r--r-- | kernel/signal.c | 34 |
2 files changed, 14 insertions, 47 deletions
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index 3a2e66d88a32..b073f3c8adc3 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h | |||
@@ -469,33 +469,6 @@ static inline int tracehook_get_signal(struct task_struct *task, | |||
469 | } | 469 | } |
470 | 470 | ||
471 | /** | 471 | /** |
472 | * tracehook_notify_jctl - report about job control stop/continue | ||
473 | * @notify: zero, %CLD_STOPPED or %CLD_CONTINUED | ||
474 | * @why: %CLD_STOPPED or %CLD_CONTINUED | ||
475 | * | ||
476 | * This is called when we might call do_notify_parent_cldstop(). | ||
477 | * | ||
478 | * @notify is zero if we would not ordinarily send a %SIGCHLD, | ||
479 | * or is the %CLD_STOPPED or %CLD_CONTINUED .si_code for %SIGCHLD. | ||
480 | * | ||
481 | * @why is %CLD_STOPPED when about to stop for job control; | ||
482 | * we are already in %TASK_STOPPED state, about to call schedule(). | ||
483 | * It might also be that we have just exited (check %PF_EXITING), | ||
484 | * but need to report that a group-wide stop is complete. | ||
485 | * | ||
486 | * @why is %CLD_CONTINUED when waking up after job control stop and | ||
487 | * ready to make a delayed @notify report. | ||
488 | * | ||
489 | * Return the %CLD_* value for %SIGCHLD, or zero to generate no signal. | ||
490 | * | ||
491 | * Called with the siglock held. | ||
492 | */ | ||
493 | static inline int tracehook_notify_jctl(int notify, int why) | ||
494 | { | ||
495 | return notify ?: (current->ptrace & PT_PTRACED) ? why : 0; | ||
496 | } | ||
497 | |||
498 | /** | ||
499 | * tracehook_finish_jctl - report about return from job control stop | 472 | * tracehook_finish_jctl - report about return from job control stop |
500 | * | 473 | * |
501 | * This is called by do_signal_stop() after wakeup. | 474 | * This is called by do_signal_stop() after wakeup. |
diff --git a/kernel/signal.c b/kernel/signal.c index f4db76986ec1..03d874e1058f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -1727,7 +1727,7 @@ void ptrace_notify(int exit_code) | |||
1727 | static int do_signal_stop(int signr) | 1727 | static int do_signal_stop(int signr) |
1728 | { | 1728 | { |
1729 | struct signal_struct *sig = current->signal; | 1729 | struct signal_struct *sig = current->signal; |
1730 | int notify; | 1730 | int notify = 0; |
1731 | 1731 | ||
1732 | if (!sig->group_stop_count) { | 1732 | if (!sig->group_stop_count) { |
1733 | struct task_struct *t; | 1733 | struct task_struct *t; |
@@ -1759,19 +1759,16 @@ static int do_signal_stop(int signr) | |||
1759 | * a group stop in progress and we are the last to stop, report | 1759 | * a group stop in progress and we are the last to stop, report |
1760 | * to the parent. When ptraced, every thread reports itself. | 1760 | * to the parent. When ptraced, every thread reports itself. |
1761 | */ | 1761 | */ |
1762 | notify = sig->group_stop_count == 1 ? CLD_STOPPED : 0; | 1762 | if (!--sig->group_stop_count) { |
1763 | notify = tracehook_notify_jctl(notify, CLD_STOPPED); | 1763 | sig->flags = SIGNAL_STOP_STOPPED; |
1764 | /* | 1764 | notify = CLD_STOPPED; |
1765 | * tracehook_notify_jctl() can drop and reacquire siglock, so | ||
1766 | * we keep ->group_stop_count != 0 before the call. If SIGCONT | ||
1767 | * or SIGKILL comes in between ->group_stop_count == 0. | ||
1768 | */ | ||
1769 | if (sig->group_stop_count) { | ||
1770 | if (!--sig->group_stop_count) | ||
1771 | sig->flags = SIGNAL_STOP_STOPPED; | ||
1772 | current->exit_code = sig->group_exit_code; | ||
1773 | __set_current_state(TASK_STOPPED); | ||
1774 | } | 1765 | } |
1766 | if (task_ptrace(current)) | ||
1767 | notify = CLD_STOPPED; | ||
1768 | |||
1769 | current->exit_code = sig->group_exit_code; | ||
1770 | __set_current_state(TASK_STOPPED); | ||
1771 | |||
1775 | spin_unlock_irq(¤t->sighand->siglock); | 1772 | spin_unlock_irq(¤t->sighand->siglock); |
1776 | 1773 | ||
1777 | if (notify) { | 1774 | if (notify) { |
@@ -1860,14 +1857,11 @@ relock: | |||
1860 | 1857 | ||
1861 | signal->flags &= ~SIGNAL_CLD_MASK; | 1858 | signal->flags &= ~SIGNAL_CLD_MASK; |
1862 | 1859 | ||
1863 | why = tracehook_notify_jctl(why, CLD_CONTINUED); | ||
1864 | spin_unlock_irq(&sighand->siglock); | 1860 | spin_unlock_irq(&sighand->siglock); |
1865 | 1861 | ||
1866 | if (why) { | 1862 | read_lock(&tasklist_lock); |
1867 | read_lock(&tasklist_lock); | 1863 | do_notify_parent_cldstop(current->group_leader, why); |
1868 | do_notify_parent_cldstop(current->group_leader, why); | 1864 | read_unlock(&tasklist_lock); |
1869 | read_unlock(&tasklist_lock); | ||
1870 | } | ||
1871 | goto relock; | 1865 | goto relock; |
1872 | } | 1866 | } |
1873 | 1867 | ||
@@ -2034,7 +2028,7 @@ void exit_signals(struct task_struct *tsk) | |||
2034 | if (unlikely(tsk->signal->group_stop_count) && | 2028 | if (unlikely(tsk->signal->group_stop_count) && |
2035 | !--tsk->signal->group_stop_count) { | 2029 | !--tsk->signal->group_stop_count) { |
2036 | tsk->signal->flags = SIGNAL_STOP_STOPPED; | 2030 | tsk->signal->flags = SIGNAL_STOP_STOPPED; |
2037 | group_stop = tracehook_notify_jctl(CLD_STOPPED, CLD_STOPPED); | 2031 | group_stop = CLD_STOPPED; |
2038 | } | 2032 | } |
2039 | out: | 2033 | out: |
2040 | spin_unlock_irq(&tsk->sighand->siglock); | 2034 | spin_unlock_irq(&tsk->sighand->siglock); |