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 [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message