]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
signal: introduce kernel_signal_stop() to fix jffs2_garbage_collect_thread()
authorOleg Nesterov <oleg@redhat.com>
Wed, 21 Oct 2015 22:03:58 +0000 (09:03 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Wed, 21 Oct 2015 22:03:58 +0000 (09:03 +1100)
jffs2_garbage_collect_thread() can race with SIGCONT and sleep in
TASK_STOPPED state after it was already sent. Add the new helper,
kernel_signal_stop(), which does this correctly.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Tejun Heo <tj@kernel.org>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Markus Pargmann <mpa@pengutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
fs/jffs2/background.c
include/linux/sched.h

index f3145fd86d86eab7ebe8944de8a5c44d7de58dd3..53cc7350af33083b5586d52566865f2c6e0ff87e 100644 (file)
@@ -132,8 +132,7 @@ static int jffs2_garbage_collect_thread(void *_c)
                        case SIGSTOP:
                                jffs2_dbg(1, "%s(): SIGSTOP received\n",
                                          __func__);
-                               set_current_state(TASK_STOPPED);
-                               schedule();
+                               kernel_signal_stop();
                                break;
 
                        case SIGKILL:
index ecd9409640c62e5d2273a70b0697c50da83d6ce5..02b63957a721a587d2f1db37e8628f869350d63c 100644 (file)
@@ -2478,6 +2478,16 @@ static inline int kernel_dequeue_signal(siginfo_t *info)
        return ret;
 }
 
+static inline void kernel_signal_stop(void)
+{
+       spin_lock_irq(&current->sighand->siglock);
+       if (current->jobctl & JOBCTL_STOP_DEQUEUED)
+               __set_current_state(TASK_STOPPED);
+       spin_unlock_irq(&current->sighand->siglock);
+
+       schedule();
+}
+
 extern void release_task(struct task_struct * p);
 extern int send_sig_info(int, struct siginfo *, struct task_struct *);
 extern int force_sigsegv(int, struct task_struct *);