I'm working on an linux application incorporating ptrace to observe the threads of another process. When the application I observe forks a child process this already works quite well. By calling waitpid in my application I can obtain the following signals in the observing application:
SIGSTOP
form the child processSIGTRAP
from the parentTo keep track of all the children I setup ptrace with PTRACE_O_TRACEFORK
, PTRACE_O_TRACEVFORK
, PTRACE_O_TRACECLONE
and PTRACE_O_TRACEEXIT
.
While everything is working quite fine with child processes, I cannot observe the threads of the application. I get the SIGTRAP
from the process creating the thread but I don't get any signals from the thread.
Is there anything special with threads and ptrace
? How does strace
keep track of threads (I could not find any special routines dedicated to threads in the code of strace
)?
This is how I use ptrace
in my application:
ptrace(PTRACE_ATTACH, pid, NULL, NULL);
waitpid()
: trace_pid = waitpid(-1, &status, 0);
ptrace
options: ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXIT);
After attaching to pid I'm calling waitpid()
in a loop and call ptrace(PTRACE_SETOPTIONS...
for every new task reported by ptrace
. Of course, I continue the tasks with SIGCONT
after event handling.
The ptrace() system call provides a means by which one process (the "tracer") may observe and control the execution of another process (the "tracee"), and examine and change the tracee's memory and registers. It is primarily used to implement breakpoint debugging and system call tracing.
Finally, ptrace() is hard to implement correctly and consistently. As a result, there has been a long history of obnoxious bugs associated with it, and user-space code which uses ptrace() tends to become encrusted with non-portable workarounds.
Because processes cannot ptrace themselves, we're forced to use spawn a child process which does that work.
ptrace provides a mechanism by which a parent process may observe and control the execution of another process. It can examine and change its core image and registers and is used primarily to implement breakpoint debugging and system call tracing.
Finally, I've found the solution myself: I got the signals from all the threads by calling
waitpid(-1, &status, __WALL)
instead of
waitpid(-1, &status, 0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With