detach() logic
Denys Vlasenko
dvlasenk at redhat.com
Wed Jun 19 11:11:56 UTC 2013
Dmitry, I am a bit worried about the flow in this function still.
Let's take a look:
error = ptrace(PTRACE_DETACH, tcp->pid, 0, 0);
if (error == 0) {
/* On a clear day, you can see forever. */
}
else if (errno != ESRCH) {
/* Shouldn't happen. */
perror_msg("detach: ptrace(PTRACE_DETACH, ...)");
}
else
/* ESRCH: process is either not stopped or doesn't exist. */
if (my_tkill(tcp->pid, 0) < 0) {
if (errno != ESRCH)
/* Shouldn't happen. */
perror_msg("detach: checking sanity");
/* else: process doesn't exist. */
^^^^^^^^^^^^^^^^^
Well, it may not exist already, but was it *waited for*?
IOW: we may still need to enter waitpid loop.
This may rarely trigger - say, we do "strace -p PROCESS",
and process exits just as we ^C the strace,
and we may end up here.
OTOH, not-waited-for child reparents to init when we exit,
so... do we ever detach() NOT not strace exit, where dead
children are a problem? I see one location:
if (event == PTRACE_EVENT_EXEC) {
if (detach_on_execve && !skip_one_b_execve)
detach(tcp); /* do "-b execve" thingy */
Maybe in the name of correctness we should wait for the process
if we see ESRCH? Possibly with WHOHANG for paranoid reasons.
}
else
/* Process is not stopped. */
if (!stop_expected) {
/* We need to stop it. */
if (use_seize)
/*
* With SEIZE, tracee can be in group-stop already.
* In this state sending it another SIGSTOP does nothing.
* Need to use INTERRUPT.
* Testcase: trying to ^C a "strace -p <stopped_process>".
*/
error = ptrace(PTRACE_INTERRUPT, tcp->pid, 0, 0);
else
error = my_tkill(tcp->pid, SIGSTOP);
if (!error)
stop_expected = 1;
^^^^^^^^^^^^
And if it was a ESRCH?
The above reasoning about not-waited-for child applies here too.
else if (errno != ESRCH) {
if (use_seize)
perror_msg("detach: ptrace(PTRACE_INTERRUPT, ...)");
else
perror_msg("detach: stopping child");
}
}
}
^^^^^^^^^^^^^^^^^^^^^
Another, lesser concern is semi-cryptic messages.
"detach: checking sanity: <ERRNO>"?
What user is supposed to understand from this message?
if (stop_expected) {
for (;;) {
#ifdef __WALL
if (waitpid(tcp->pid, &status, __WALL) < 0) {
What do you think?
More information about the Strace-devel
mailing list