Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a13049e authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Linus Torvalds
Browse files

signal: introduce kernel_signal_stop() to fix jffs2_garbage_collect_thread()



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: default avatarOleg Nesterov <oleg@redhat.com>
Reviewed-by: default avatarTejun 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent be0e6f29
Loading
Loading
Loading
Loading
+1 −2
Original line number Original line Diff line number Diff line
@@ -132,8 +132,7 @@ static int jffs2_garbage_collect_thread(void *_c)
			case SIGSTOP:
			case SIGSTOP:
				jffs2_dbg(1, "%s(): SIGSTOP received\n",
				jffs2_dbg(1, "%s(): SIGSTOP received\n",
					  __func__);
					  __func__);
				set_current_state(TASK_STOPPED);
				kernel_signal_stop();
				schedule();
				break;
				break;


			case SIGKILL:
			case SIGKILL:
+10 −0
Original line number Original line Diff line number Diff line
@@ -2475,6 +2475,16 @@ static inline int kernel_dequeue_signal(siginfo_t *info)
	return ret;
	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 void release_task(struct task_struct * p);
extern int send_sig_info(int, struct siginfo *, struct task_struct *);
extern int send_sig_info(int, struct siginfo *, struct task_struct *);
extern int force_sigsegv(int, struct task_struct *);
extern int force_sigsegv(int, struct task_struct *);