Commit 81be24b8 authored by Tejun Heo's avatar Tejun Heo Committed by Oleg Nesterov
Browse files

ptrace: relocate set_current_state(TASK_TRACED) in ptrace_stop()



In ptrace_stop(), after arch hook is done, the task state and jobctl
bits are updated while holding siglock.  The ordering requirement
there is that TASK_TRACED is set before JOBCTL_TRAPPING is cleared to
prevent ptracer waiting on TRAPPING doesn't end up waking up TRACED is
actually set and sees TASK_RUNNING in wait(2).

Move set_current_state(TASK_TRACED) to the top of the block and
reorganize comments.  This makes the ordering more obvious
(TASK_TRACED before other updates) and helps future updates to group
stop participation.

This patch doesn't cause any functional change.

Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
parent 755e276b
Loading
Loading
Loading
Loading
+13 −15
Original line number Diff line number Diff line
@@ -1732,6 +1732,18 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
			return;
	}

	/*
	 * We're committing to trapping.  TRACED should be visible before
	 * TRAPPING is cleared; otherwise, the tracer might fail do_wait().
	 * Also, transition to TRACED and updates to ->jobctl should be
	 * atomic with respect to siglock and should be done after the arch
	 * hook as siglock is released and regrabbed across it.
	 */
	set_current_state(TASK_TRACED);

	current->last_siginfo = info;
	current->exit_code = exit_code;

	/*
	 * If @why is CLD_STOPPED, we're trapping to participate in a group
	 * stop.  Do the bookkeeping.  Note that if SIGCONT was delievered
@@ -1742,21 +1754,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
	if (why == CLD_STOPPED && (current->jobctl & JOBCTL_STOP_PENDING))
		gstop_done = task_participate_group_stop(current);

	current->last_siginfo = info;
	current->exit_code = exit_code;

	/*
	 * TRACED should be visible before TRAPPING is cleared; otherwise,
	 * the tracer might fail do_wait().
	 */
	set_current_state(TASK_TRACED);

	/*
	 * We're committing to trapping.  Clearing JOBCTL_TRAPPING and
	 * transition to TASK_TRACED should be atomic with respect to
	 * siglock.  This should be done after the arch hook as siglock is
	 * released and regrabbed across it.
	 */
	/* entering a trap, clear TRAPPING */
	task_clear_jobctl_trapping(current);

	spin_unlock_irq(&current->sighand->siglock);