RSS | technovelty home | page of ian | ianw@ieee.org
Today I wanted a way to run a program to completion but stop it
just before it is destroyed, therefore allowing me to inspect some
/proc variables I was interested in.
As it happens the ptrace option
PTRACE_O_TRACEEXIT is designed for just that. To use it,
you first either attach to the process, or if forking a new process
call PTRACE_TRACEME and exec as usual.
Then you use the ptrace call
PTRACE_SETOPTIONS with the
PTRACE_O_TRACEEXIT option in the data
pointer, and wait for the traced process as usual
(unfortunately due to a bug you
will have to clag the #defines from the kernel header for
now). There are now two conditions to handle:
SIGTRAP with the
PTRACE_EVENT_EXIT status set, signalling to us that it
has exited. This is a terminal state; you can inspect the registers,
etc, but the process can not come back to life now. This status is
"overloaded" in the status returned by wait, e.g.
/* wait for signal from child */
waitpid(pid, &status, 0);
/* any signal stops the child, so check that the incoming signal is a
SIGTRAP and the event_exit flag is set */
if ((WSTOPSIG(status) == SIGTRAP) &&
(status & (PTRACE_EVENT_EXIT << 8)))
...
PTRACE_CONT call specifing the signal in the
data pointer; e.g.
/* if not, pass the original signal onto the child */
if (ptrace(PTRACE_CONT, pid, 0, WSTOPSIG(status))) {
perror("stopper: ptrace(PTRACE_CONT, ...)");
exit(1);
}
A straight forward example is stopper.c. The program allows you to run a program (or attach to a running program) and effecitvley pause it just before it exits, allowing you to inspect it and then manually dispose of it once you have the data you need.
posted at: Wed, 16 May 2007 13:32 | in /linux | permalink | add comment (1 others)

This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.