mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 14:25:49 +00:00
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: Andrew Vagin <avagin@virtuozzo.com> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
committed by
Pavel Emelyanov
parent
8135e26ae3
commit
6cc316615c
19
ptrace.c
19
ptrace.c
@@ -31,11 +31,22 @@ int unseize_task(pid_t pid, int orig_st, int st)
|
||||
kill(pid, SIGKILL);
|
||||
return 0;
|
||||
} else if (st == TASK_STOPPED) {
|
||||
if (orig_st == TASK_ALIVE)
|
||||
kill(pid, SIGSTOP);
|
||||
/* PTRACE_SEIZE will restore state of other tasks */
|
||||
/*
|
||||
* 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);
|
||||
} 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
|
||||
pr_err("Unknown final state %d\n", st);
|
||||
|
||||
|
Reference in New Issue
Block a user