On x86 Linux 2.2.12, I can't figure out a reliable way to keep a
process stopped after ptrace operations.
For example, after this sequence
ptrace(PTRACE_ATTACH, pid, 0, 0);
waitpid(pid, NULL, 0);
ptrace(PTRACE_DETACH, pid, 0, SIGSTOP);
the process (pid) is not stopped. So this does not help me.
After this sequence
ptrace(PTRACE_ATTACH, pid, 0, 0); (Sequence 1)
waitpid(pid, NULL, 0);
kill(pid, SIGSTOP);
ptrace(PTRACE_DETACH, pid, 0, 0);
the process is stopped. However, following it with this sequence
ptrace(PTRACE_ATTACH, pid, 0, 0);
waitpid(pid, NULL, 0);
ptrace(PTRACE_DETACH, pid, 0, 0);
causes it to run again. On the other hand, following Sequence 1 with
this sequence (prefacing the above sequence with a sleep)
sleep(1);
ptrace(PTRACE_ATTACH, pid, 0, 0);
waitpid(pid, NULL, 0);
ptrace(PTRACE_DETACH, pid, 0, 0);
causes the process to remain stopped.
I've been trying to understand this behavior from kernel sources,
but I can't figure it out -- can anyone help me?
The program copied below demonstrates the behavior I describe. My
questions in terms of this program are
- why does the child stop for arg==2, but not arg==1?
- why does the child stop for arg==4, but not arg==3?
My real problem is I need a way to keep a process stopped across
multiple ptrace attach/detach operations. Does anyone have a reliable
technique?
Thanks,
Vic Zandy
#include <sys/ptrace.h>
#include <signal.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int arg, pid;
arg = atoi(argv[1]);
pid = fork();
if (pid == 0)
while (1) {
sleep(1);
printf("I'm running\n");
}
if (arg == 1) {
ptrace(PTRACE_ATTACH, pid, 0, 0);
waitpid(pid, NULL, 0);
ptrace(PTRACE_DETACH, pid, 0, SIGSTOP);
/* child is left RUNNING */
} else if (arg == 2) {
ptrace(PTRACE_ATTACH, pid, 0, 0);
waitpid(pid, NULL, 0);
kill(pid, SIGSTOP);
ptrace(PTRACE_DETACH, pid, 0, 0);
/* child is left STOPPED */
} else if (arg == 3) {
ptrace(PTRACE_ATTACH, pid, 0, 0);
waitpid(pid, NULL, 0);
kill(pid, SIGSTOP);
ptrace(PTRACE_DETACH, pid, 0, 0);
ptrace(PTRACE_ATTACH, pid, 0, 0);
waitpid(pid, NULL, 0);
ptrace(PTRACE_DETACH, pid, 0, 0);
/* child is left RUNNING */
} else if (arg == 4) {
ptrace(PTRACE_ATTACH, pid, 0, 0);
waitpid(pid, NULL, 0);
kill(pid, SIGSTOP);
ptrace(PTRACE_DETACH, pid, 0, 0);
sleep(1);
ptrace(PTRACE_ATTACH, pid, 0, 0);
waitpid(pid, NULL, 0);
ptrace(PTRACE_DETACH, pid, 0, 0);
/* child is left STOPPED */
}
while (1)
;
return 0;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Thu Mar 23 2000 - 21:00:23 EST