All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tejun Heo <tj@kernel.org>
To: oleg@redhat.com
Cc: vda.linux@googlemail.com, jan.kratochvil@redhat.com,
	linux-kernel@vger.kernel.org, torvalds@linux-foundation.org,
	akpm@linux-foundation.org, indan@nul.nu, bdonlan@gmail.com,
	pedro@codesourcery.com, Tejun Heo <tj@kernel.org>
Subject: [PATCH 07/17] job control: introduce task_set_jobctl_pending()
Date: Mon, 30 May 2011 01:12:30 +0200	[thread overview]
Message-ID: <1306710760-16440-8-git-send-email-tj@kernel.org> (raw)
In-Reply-To: <1306710760-16440-1-git-send-email-tj@kernel.org>

task->jobctl currently hosts JOBCTL_STOP_PENDING and will host TRAP
pending bits too.  Setting pending conditions on a dying task may make
the task unkillable.  Currently, each setting site is responsible for
checking for the condition but with to-be-added job control traps this
becomes too fragile.

This patch adds task_set_jobctl_pending() which should be used when
setting task->jobctl bits to schedule a stop or trap.  The function
performs the followings to ease setting pending bits.

* Sanity checks.

* If fatal signal is pending or PF_EXITING is set, no bit is set.

* STOP_SIGMASK is automatically cleared if new value is being set.

do_signal_stop() and ptrace_attach() are updated to use
task_set_jobctl_pending() instead of setting STOP_PENDING explicitly.
The surrounding structures around setting are changed to fit
task_set_jobctl_pending() better but there should be no userland
visible behavior difference.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Oleg Nesterov <oleg@redhat.com>
---
 include/linux/sched.h |    2 ++
 kernel/ptrace.c       |    6 +++---
 kernel/signal.c       |   46 ++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index 11791dd..bc7a380 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1819,6 +1819,8 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *
 
 #define JOBCTL_PENDING_MASK	JOBCTL_STOP_PENDING
 
+extern bool task_set_jobctl_pending(struct task_struct *task,
+				    unsigned int mask);
 extern void task_clear_jobctl_pending(struct task_struct *task,
 				      unsigned int mask);
 
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index cbda3c2..1506556 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -256,10 +256,10 @@ static int ptrace_attach(struct task_struct *task)
 	 * The following task_is_stopped() test is safe as both transitions
 	 * in and out of STOPPED are protected by siglock.
 	 */
-	if (task_is_stopped(task)) {
-		task->jobctl |= JOBCTL_STOP_PENDING | JOBCTL_TRAPPING;
+	if (task_is_stopped(task) &&
+	    task_set_jobctl_pending(task,
+				    JOBCTL_STOP_PENDING | JOBCTL_TRAPPING))
 		signal_wake_up(task, 1);
-	}
 
 	spin_unlock(&task->sighand->siglock);
 
diff --git a/kernel/signal.c b/kernel/signal.c
index 637a171..9ab91c5 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -224,6 +224,39 @@ static inline void print_dropped_signal(int sig)
 }
 
 /**
+ * task_set_jobctl_pending - set jobctl pending bits
+ * @task: target task
+ * @mask: pending bits to set
+ *
+ * Clear @mask from @task->jobctl.  @mask must be subset of
+ * %JOBCTL_PENDING_MASK | %JOBCTL_STOP_CONSUME | %JOBCTL_STOP_SIGMASK |
+ * %JOBCTL_TRAPPING.  If stop signo is being set, the existing signo is
+ * cleared.  If @task is already being killed or exiting, this function
+ * becomes noop.
+ *
+ * CONTEXT:
+ * Must be called with @task->sighand->siglock held.
+ *
+ * RETURNS:
+ * %true if @mask is set, %false if made noop because @task was dying.
+ */
+bool task_set_jobctl_pending(struct task_struct *task, unsigned int mask)
+{
+	BUG_ON(mask & ~(JOBCTL_PENDING_MASK | JOBCTL_STOP_CONSUME |
+			JOBCTL_STOP_SIGMASK | JOBCTL_TRAPPING));
+	BUG_ON((mask & JOBCTL_TRAPPING) && !(mask & JOBCTL_PENDING_MASK));
+
+	if (unlikely(fatal_signal_pending(task) || (task->flags & PF_EXITING)))
+		return false;
+
+	if (mask & JOBCTL_STOP_SIGMASK)
+		task->jobctl &= ~JOBCTL_STOP_SIGMASK;
+
+	task->jobctl |= mask;
+	return true;
+}
+
+/**
  * task_clear_jobctl_trapping - clear jobctl trapping bit
  * @task: target task
  *
@@ -1902,19 +1935,20 @@ static int do_signal_stop(int signr)
 		else
 			WARN_ON_ONCE(!task_ptrace(current));
 
-		current->jobctl &= ~JOBCTL_STOP_SIGMASK;
-		current->jobctl |= signr | gstop;
-		sig->group_stop_count = 1;
+		sig->group_stop_count = 0;
+
+		if (task_set_jobctl_pending(current, signr | gstop))
+			sig->group_stop_count++;
+
 		for (t = next_thread(current); t != current;
 		     t = next_thread(t)) {
-			t->jobctl &= ~JOBCTL_STOP_SIGMASK;
 			/*
 			 * Setting state to TASK_STOPPED for a group
 			 * stop is always done with the siglock held,
 			 * so this check has no races.
 			 */
-			if (!(t->flags & PF_EXITING) && !task_is_stopped(t)) {
-				t->jobctl |= signr | gstop;
+			if (!task_is_stopped(t) &&
+			    task_set_jobctl_pending(t, signr | gstop)) {
 				sig->group_stop_count++;
 				signal_wake_up(t, 0);
 			}
-- 
1.7.5.2


  parent reply	other threads:[~2011-05-29 23:13 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-29 23:12 [PATCHSET ptrace] ptrace: implement PTRACE_SEIZE/INTERRUPT and group stop notification, take#4 Tejun Heo
2011-05-29 23:12 ` [PATCH 01/17] ptrace: remove silly wait_trap variable from ptrace_attach() Tejun Heo
2011-06-01 18:47   ` Oleg Nesterov
2011-06-02  5:03     ` Tejun Heo
2011-06-02 11:39   ` [PATCH UPDATED " Tejun Heo
2011-05-29 23:12 ` [PATCH 02/17] job control: rename signal->group_stop and flags to jobctl and update them Tejun Heo
2011-05-29 23:12 ` [PATCH 03/17] ptrace: ptrace_check_attach(): rename @kill to @ignore_state and add comments Tejun Heo
2011-05-29 23:12 ` [PATCH 04/17] ptrace: relocate set_current_state(TASK_TRACED) in ptrace_stop() Tejun Heo
2011-05-29 23:12 ` [PATCH 05/17] job control: introduce JOBCTL_PENDING_MASK and task_clear_jobctl_pending() Tejun Heo
2011-05-29 23:12 ` [PATCH 06/17] job control: make task_clear_jobctl_pending() clear TRAPPING automatically Tejun Heo
2011-05-29 23:12 ` Tejun Heo [this message]
2011-05-29 23:12 ` [PATCH 08/17] ptrace: use bit_waitqueue for TRAPPING instead of wait_chldexit Tejun Heo
2011-06-02 11:41   ` [PATCH UPDATED " Tejun Heo
2011-05-29 23:12 ` [PATCH 09/17] signal: remove three noop tracehooks Tejun Heo
2011-05-29 23:12 ` [PATCH 10/17] job control: introduce JOBCTL_TRAP_STOP and use it for group stop trap Tejun Heo
2011-05-29 23:12 ` [PATCH 11/17] ptrace: implement PTRACE_SEIZE Tejun Heo
2011-06-01 19:01   ` Oleg Nesterov
2011-06-01 19:55     ` Oleg Nesterov
2011-06-02  5:13     ` Tejun Heo
2011-06-02 11:43   ` [PATCH UPDATED " Tejun Heo
2011-05-29 23:12 ` [PATCH 12/17] ptrace: implement PTRACE_INTERRUPT Tejun Heo
2011-05-29 23:12 ` [PATCH 13/17] ptrace: add siginfo.si_pt_flags Tejun Heo
2011-05-29 23:12 ` [PATCH 14/17] ptrace: make group stop state visible via PTRACE_GETSIGINFO Tejun Heo
2011-05-29 23:12 ` [PATCH 15/17] ptrace: don't let PTRACE_SETSIGINFO override __SI_TRAP siginfo Tejun Heo
2011-05-29 23:12 ` [PATCH 16/17] ptrace: implement TRAP_NOTIFY and use it for group stop events Tejun Heo
2011-05-29 23:12 ` [PATCH 17/17] ptrace: implement PTRACE_LISTEN Tejun Heo
2011-06-02 17:33   ` Oleg Nesterov
2011-06-13 14:10     ` Tejun Heo
2011-06-13 20:33       ` Oleg Nesterov
2011-06-14  6:45         ` Tejun Heo
2011-05-30 15:42 ` [PATCHSET ptrace] ptrace: implement PTRACE_SEIZE/INTERRUPT and group stop notification, take#4 Oleg Nesterov
2011-06-01  5:39   ` Tejun Heo
2011-06-02 12:31     ` Tejun Heo
2011-06-02 14:51       ` Denys Vlasenko
2011-06-03  1:24         ` Tejun Heo
2011-06-03 10:25           ` Pedro Alves
2011-06-16  8:38             ` Tejun Heo
2011-06-16  9:56               ` Pedro Alves
2011-06-17 19:08                 ` Oleg Nesterov
2011-06-03 11:57           ` Denys Vlasenko
2011-06-03 12:11             ` Pedro Alves
2011-06-03 14:12               ` Denys Vlasenko
2011-06-03 15:24                 ` Pedro Alves
2011-06-03 15:46             ` Oleg Nesterov
2011-06-02 18:27       ` Oleg Nesterov
2011-06-02 21:09         ` Denys Vlasenko
2011-06-03  1:34           ` Tejun Heo
2011-06-03 11:37             ` Denys Vlasenko
2011-06-03 11:58               ` Denys Vlasenko
2011-06-03 15:37             ` Oleg Nesterov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1306710760-16440-8-git-send-email-tj@kernel.org \
    --to=tj@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=bdonlan@gmail.com \
    --cc=indan@nul.nu \
    --cc=jan.kratochvil@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=oleg@redhat.com \
    --cc=pedro@codesourcery.com \
    --cc=torvalds@linux-foundation.org \
    --cc=vda.linux@googlemail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.