--- DOCa 2011-05-20 21:52:24.152964068 +0200 +++ DOCb.txt 2011-05-30 16:03:34.878790225 +0200 @@ -105,16 +105,39 @@ When running tracee enters ptrace-stop, it notifies its tracer using waitpid API. Tracer should use waitpid family of syscalls to wait for tracee to stop. Most of this document assumes that tracer waits with: + pid = waitpid(pid_or_minus_1, &status, __WALL); + Ptrace-stopped tracees are reported as returns with pid > 0 and WIFSTOPPED(status) == true. -??? any pitfalls with WNOHANG (I remember that there are bugs in this - area)? effects of WSTOPPED, WEXITED, WCONTINUED bits? Are they ok? - waitid usage? WNOWAIT? +??? Do we require __WALL usage, or will just using 0 be ok? Are the +rules different if user wants to use waitid? + +__WALL value does not include WSTOPPED and WEXITED bits, but implies +their functionality. + +Setting of WCONTINUED bit in waitpid flags is not recommended: the +continued state is per-process and consuming it would confuse real +parent of the tracee. + +Use of WNOHANG bit in waitpid flags may cause waitpid return 0 ("no +wait results available yet") even if tracer knows there should be a +notification. Example: kill(tracee, SIGKILL); waitpid(tracee, &status, +__WALL | WNOHANG); + +??? waitid usage? WNOWAIT? ??? describe how wait notifications queue (or not queue) +The following kinds of ptrace-stops exist: signal-delivery-stops, +group-stop, PTRACE_EVENT stops, syscall-stops [, SINGLESTEP, SYSEMU, +SYSEMU_SINGLESTEP]. They all are reported as waitpid result with +WIFSTOPPED(status) == true. They may be differentiated by checking +(status >> 8) value (note that WSTOPSIG(status) is (status >> 8) & +0xff) and if looking at (status >> 8) value doesn't resolve ambiguity, +by querying PTRACE_GETSIGINFO. + 1.x.x Signal-delivery-stop @@ -186,7 +209,8 @@ PTRACE_GETSIGINFO can be used to retrieve siginfo_t structure which corresponds to delivered signal. PTRACE_SETSIGINFO may be used to modify it. If PTRACE_SETSIGINFO has been used to alter siginfo_t, -si_signo field and sig parameter in restarting command must match. +si_signo field and sig parameter in restarting command must match, +otherwise the result is undefined. 1.x.x Group-stop @@ -207,8 +231,9 @@ call. The call can be avoided if signal number is not SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU - only these four signals are stopping signals. If tracer sees something else, it can't be group-stop. Otherwise, tracer -needs to call PTRACE_GETSIGINFO. If PTRACE_GETSIGINFO fails, then it is -definitely a group-stop. +needs to call PTRACE_GETSIGINFO. If PTRACE_GETSIGINFO fails with +EINVAL, then it is definitely a group-stop. (Other failure codes are +possible, such as ESRCH "no such process" if SIGKILL killed the tracee). As of kernel 2.6.38, after tracer sees tracee ptrace-stop and until it restarts or kills it, tracee will not run, and will not send @@ -278,20 +303,24 @@ SIGTRAP. If PTRACE_O_TRACESYSGOOD option was set by tracer, then WSTOPSIG(status) == (SIGTRAP | 0x80). -There is no portable way to distinguish them from signal-delivery-stop -with SIGTRAP. Some architectures allow to distinguish them by examining -registers. For example, on x86 rax = -ENOSYS in syscall-enter-stop. -Since SIGTRAP (like any other signal) always happens *after* -syscall-exit-stop, and at this point rax almost never contains -ENOSYS, -SIGTRAP looks like "syscall-stop which is not syscall-enter-stop", IOW: -it looks like a "stray syscall-exit-stop" and can be detected this way. -But such detection is fragile and is best avoided. Using -PTRACE_O_TRACESYSGOOD option is a recommended method. - -??? can be distinguished by PTRACE_GETSIGINFO, si_code <= 0 if sent by -usual suspects like [t]kill, sigqueue; or = SI_KERNEL (0x80) if sent by +Syscall-stops can be distinguished from signal-delivery-stop with +SIGTRAP by querying PTRACE_GETSIGINFO: si_code <= 0 if sent by usual +suspects like [tg]kill/sigqueue/etc; or = SI_KERNEL (0x80) if sent by kernel, whereas syscall-stops have si_code = SIGTRAP or (SIGTRAP | -0x80). Right? Should this be documented? +0x80). However, syscall-stops happen very often (twice per syscall), +and performing PTRACE_GETSIGINFO for every syscall-stop may be somewhat +expensive. + +Some architectures allow to distinguish them by examining registers. +For example, on x86 rax = -ENOSYS in syscall-enter-stop. Since SIGTRAP +(like any other signal) always happens *after* syscall-exit-stop, and +at this point rax almost never contains -ENOSYS, SIGTRAP looks like +"syscall-stop which is not syscall-enter-stop", IOW: it looks like a +"stray syscall-exit-stop" and can be detected this way. But such +detection is fragile and is best avoided. + +Using PTRACE_O_TRACESYSGOOD option is a recommended method, since it is +reliable and does not incur performance penalty. Syscall-enter-stop and syscall-exit-stop are indistinguishable from each other by tracer. Tracer needs to keep track of the sequence of @@ -387,11 +416,9 @@ this can race with concurrent SIGSTOPs. Another complication is that tracee may enter other ptrace-stops and needs to be restarted and waited for again, until SIGSTOP is seen. Yet another complication is to -be sure that tracee is not already group-stopped, because no signal +be sure that tracee is not already ptrace-stopped, because no signal delivery happens while it is - not even SIGSTOP. -??? is above accurate? - ??? Describe how to detach from a group-stopped tracee so that it doesn't run, but continues to wait for SIGCONT.