Stopping ptraced processes

From: Victor Zandy (zandy@cs.wisc.edu)
Date: Fri Mar 17 2000 - 19:00:06 EST

  • Next message: Mirian Crzig Lennox: "Re: Avoiding OOM on overcommit...?"

        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 : Sat Mar 18 2000 - 09:24:04 EST