Skip to content

Commit

Permalink
signal: introduce kernel_signal_stop() to fix jffs2_garbage_collect_t…
Browse files Browse the repository at this point in the history
…hread()

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 <[email protected]>
Reviewed-by: Tejun Heo <[email protected]>
Cc: David Woodhouse <[email protected]>
Cc: Felipe Balbi <[email protected]>
Cc: Markus Pargmann <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
oleg-nesterov authored and torvalds committed Nov 7, 2015
1 parent be0e6f2 commit 9a13049
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 2 deletions.
3 changes: 1 addition & 2 deletions fs/jffs2/background.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
10 changes: 10 additions & 0 deletions include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -2475,6 +2475,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 *);
Expand Down

0 comments on commit 9a13049

Please sign in to comment.