detach() logic

Denys Vlasenko dvlasenk at
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, ...)");
                /* 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.

                /* 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);
                                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, ...)");
                                        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