Commit 6cc31661 authored by Andrew Vagin's avatar Andrew Vagin Committed by Pavel Emelyanov

ptrace: send SIGSTOP to restore the stopped state

If a task was in a stopped state before we started to ptrace-seize
it, this stopped state will be restored by kernel upon detach.

If SIGSTOP was only in a task queue, we need to send it by hands
again bedore detaching. Otherwise we clean stop from queue (to
run parasite) and seize will restore task as running.

And, since SIGSTOP doesn't affect states of already stopped tasks,
we can send it to then safely and not distinguish stopped from
stop-queued ones.

Reported-by: Mr Jenkins
Signed-off-by: 's avatarAndrew Vagin <avagin@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 8135e26a
...@@ -31,11 +31,22 @@ int unseize_task(pid_t pid, int orig_st, int st) ...@@ -31,11 +31,22 @@ int unseize_task(pid_t pid, int orig_st, int st)
kill(pid, SIGKILL); kill(pid, SIGKILL);
return 0; return 0;
} else if (st == TASK_STOPPED) { } else if (st == TASK_STOPPED) {
if (orig_st == TASK_ALIVE) /*
* Task might have had STOP in queue. We detected such
* guy as TASK_STOPPED, but cleared signal to run the
* parasite code. hus after detach the task will become
* running. That said -- STOP everyone regardless of
* the initial state.
*/
kill(pid, SIGSTOP); kill(pid, SIGSTOP);
/* PTRACE_SEIZE will restore state of other tasks */
} else if (st == TASK_ALIVE) { } else if (st == TASK_ALIVE) {
/* do nothing */ ; /*
* Same as in the comment above -- there might be a
* task with STOP in queue that would get lost after
* detach, so stop it again.
*/
if (orig_st == TASK_STOPPED)
kill(pid, SIGSTOP);
} else } else
pr_err("Unknown final state %d\n", st); pr_err("Unknown final state %d\n", st);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment