Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Sep 2000 09:20:40 -0400 (EDT)
From:      Patrick Alken <cosine@ellipse.mcs.drexel.edu>
To:        freebsd-hackers@freebsd.org
Subject:   ptrace question
Message-ID:  <Pine.BSF.4.21.0009280920220.11255-100000@ellipse.mcs.drexel.edu>

next in thread | raw e-mail | index | archive | help
 Below I have provided a sample program to demonstrate the problem I am
having. Basically, when I ptrace() an ncurses program (such has ncftp
2.4.3), I cannot do a PT_CONTINUE followed by a PT_STEP normally.

 To demonstrate, the program gets ncftp ready for ptracing and then calls
ptrace() with PT_CONTINUE on it. This works perfectly, and if the program
receives a signal, such as a SIGINT from a CTRL-C, I then attempt to use
ptrace() with PT_STEP, to single-step the next instruction. This is where
it fails.

 The wait() call after the ptrace(PT_STEP) call does not return until you
hit the ENTER key, and I cannot figure out why. The first wait() call
after the ptrace(PT_CONTINUE) returns normally, but when I use it after
the singlestep call, it will not return normally unless I hit a key.

 As a side note, if I use ptrace(PT_CONTINUE) a second time (instead of
PT_STEP), the wait() call will return normally without having to hit a
key.
 Also, if I run a non-ncurses program through this same procedure, the
wait() after the ptrace(PT_STEP) operates normally. I can only reproduce
this problem under ncurses programs like ncftp v2.4.3 - but I did use
tcgetattr() and tcsetattr() to reset the terminal settings, so I don't
know why ncurses would be affecting it.

 If anyone knows what the problem could be, please let me know!

---- Cut here ----

/*
 * The goal of this program is to run an ncurses program normally
 * until a signal is caught, and then try to singlestep one
 * instruction. It should demonstrate that the wait() call after
 * the ptrace() singlestep call does not return as it should - 
 * you need to hit the ENTER key for the wait() call to return.
 *
 * Compile: gcc -o ptest ptest.c
 *
 * Run: ./ptest, hit ^C and you will see that you must hit
 *      a keystroke to get it to continue past the singlestep.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <errno.h>
#include <sys/wait.h>
#include <signal.h>
#include <termios.h>
#include <unistd.h>

/*
 * Location of an ncurses program (NcFTP v2.x.x)
 */
char filename[] = "/usr/local/bin/ncftp2";

int
main()

{
  int pid; /* child pid */
  int waitval;
  int sig;
  struct termios SavedAttributes;

  signal(SIGINT, SIG_IGN);

  pid = fork();
  switch (pid)
  {
    case -1:
    {
      perror("fork");
      break;
    }

    /*
     * Child
     */
    case 0:
    {
      /*
       * Allow parent to trace this child process
       */
      ptrace(PT_TRACE_ME, 0, 0, 0);
      
      /*
       * Execute program to be debugged and cause child to
       * send a signal to parent, so the parent can switch
       * to PT_STEP
       */
      execl(filename, filename, NULL);

      break;
    }

    /*
     * Parent
     */
    default:
    {
      /* 
       * Wait for child to stop (execl)
       */
      wait(&waitval);

      /* save attributes */
      tcgetattr(STDIN_FILENO, &SavedAttributes);

      if (ptrace(PT_CONTINUE, pid, (caddr_t) 1, 0) != 0)
        perror("ptrace");

      wait(&waitval);

      /* restore attributes */
      tcsetattr(STDIN_FILENO, TCSANOW, &SavedAttributes);

      fprintf(stderr, "\nwaitval1 = %d\n", waitval);

      if (WIFSTOPPED(waitval))
      {
        sig = WSTOPSIG(waitval);
        fprintf(stderr, "signal = %d\n", sig);

        /*
         * OK, they did the CONTROL-C, now try singlestepping the
         * next instruction.
         */

        fprintf(stderr, "SINGLESTEPPING - here is where you have to hit ENTER but shouldn't need to\n");

        if (ptrace(PT_STEP, pid, (caddr_t) 1, 0) != 0)
          perror("ptrace");

        /*
         * Here is where you have to hit a key to get wait() to
         * return???
         */
        wait(&waitval);

        tcsetattr(STDIN_FILENO, TCSANOW, &SavedAttributes);

        fprintf(stderr, "DONE SINGLESTEP, waitval2 = %d\n", waitval);
      }
    }
  }

  return 0;
}




To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0009280920220.11255-100000>