diff options
author | Tejun Heo <tj@kernel.org> | 2011-03-23 05:37:00 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2011-03-23 05:37:00 -0400 |
commit | 39efa3ef3a376a4e53de2f82fc91182459d34200 (patch) | |
tree | f75a44fa77396edcf74e41686912554f96681340 /include/linux/sched.h | |
parent | e5c1902e9260a0075ea52cb5ef627a8d9aaede89 (diff) |
signal: Use GROUP_STOP_PENDING to stop once for a single group stop
Currently task->signal->group_stop_count is used to decide whether to
stop for group stop. However, if there is a task in the group which
is taking a long time to stop, other tasks which are continued by
ptrace would repeatedly stop for the same group stop until the group
stop is complete.
Conversely, if a ptraced task is in TASK_TRACED state, the debugger
won't get notified of group stops which is inconsistent compared to
the ptraced task in any other state.
This patch introduces GROUP_STOP_PENDING which tracks whether a task
is yet to stop for the group stop in progress. The flag is set when a
group stop starts and cleared when the task stops the first time for
the group stop, and consulted whenever whether the task should
participate in a group stop needs to be determined. Note that now
tasks in TASK_TRACED also participate in group stop.
This results in the following behavior changes.
* For a single group stop, a ptracer would see at most one stop
reported.
* A ptracee in TASK_TRACED now also participates in group stop and the
tracer would get the notification. However, as a ptraced task could
be in TASK_STOPPED state or any ptrace trap could consume group
stop, the notification may still be missing. These will be
addressed with further patches.
* A ptracee may start a group stop while one is still in progress if
the tracer let it continue with stop signal delivery. Group stop
code handles this correctly.
Oleg:
* Spotted that a task might skip signal check even when its
GROUP_STOP_PENDING is set. Fixed by updating
recalc_sigpending_tsk() to check GROUP_STOP_PENDING instead of
group_stop_count.
* Pointed out that task->group_stop should be cleared whenever
task->signal->group_stop_count is cleared. Fixed accordingly.
* Pointed out the behavior inconsistency between TASK_TRACED and
RUNNING and the last behavior change.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Cc: Roland McGrath <roland@redhat.com>
Diffstat (limited to 'include/linux/sched.h')
-rw-r--r-- | include/linux/sched.h | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index 85f51042c2b8..b2a17dfbdbad 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1775,8 +1775,11 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t * | |||
1775 | /* | 1775 | /* |
1776 | * task->group_stop flags | 1776 | * task->group_stop flags |
1777 | */ | 1777 | */ |
1778 | #define GROUP_STOP_PENDING (1 << 16) /* task should stop for group stop */ | ||
1778 | #define GROUP_STOP_CONSUME (1 << 17) /* consume group stop count */ | 1779 | #define GROUP_STOP_CONSUME (1 << 17) /* consume group stop count */ |
1779 | 1780 | ||
1781 | extern void task_clear_group_stop_pending(struct task_struct *task); | ||
1782 | |||
1780 | #ifdef CONFIG_PREEMPT_RCU | 1783 | #ifdef CONFIG_PREEMPT_RCU |
1781 | 1784 | ||
1782 | #define RCU_READ_UNLOCK_BLOCKED (1 << 0) /* blocked while in RCU read-side. */ | 1785 | #define RCU_READ_UNLOCK_BLOCKED (1 << 0) /* blocked while in RCU read-side. */ |