LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices


Reply
  Search this Thread
Old 04-11-2008, 10:29 AM   #1
ocstjf
LQ Newbie
 
Registered: Apr 2008
Posts: 6

Rep: Reputation: 0
Question ptrace ATTACH, then CONT with signal fails on FC6


ptrace behavior apparently changed big-time between FC3=RHEL4=2.6.9 and FC6=2.6.18, such that continuing the debugged process with a signal after attaching no longer works. I can work around it but I want to know if it's a bug or an intentional feature, and if a feature, when was it introduced and why?

The following is my test program. It's long and verbose, I'm sorry, but I wanted to be clear. As comments say, there are 2 ways to build it -- the one we use in our real app is -DCHILD_IS_DEBUGGER.

/*
* ptracebug.c
* Test case showing change in ptrace behavior.
* There are two variations:
* gcc ptracebug.c -o ptrace_from_parent
* gcc -DCHILD_IS_DEBUGGER ptracebug.c -o ptrace_from_child
* Both print TEST PASSED on 2.4.18, 2.6.9, but
* debugged process fails on 2.6.18=FC6.
*/
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sys/ptrace.h>
#include <linux/ptrace.h>
#include <sys/wait.h>

static char *Msg = "EXITED TOO EARLY\n";
static void AppExit(void)
{
printf("PID=%d: %s\n\n", getpid(), Msg);
}


int main (int argc, char **argv)
{
sigset_t sigset;
sigset_t oldset;
struct sigaction NewAction;

int parentpid = getpid();
int childpid;

fprintf(stderr,
"--- Show that ptrace(CONT, blocked-signal) fails on FC6\n"
" If test dones't print PASSED, it failed.\n");

/* block sigusr1, inherited by forked process */
sigemptyset (&sigset);
sigaddset (&sigset, SIGUSR1);
sigprocmask (SIG_BLOCK, &sigset, &oldset);

atexit(AppExit);

/* fork */
childpid = fork ();

if (childpid < 0)
{
perror("fork failed\n");
return 0;
}

#ifdef CHILD_IS_DEBUGGER
if (childpid == 0)
{ /* child */
int deb = getpid();
int app = parentpid;
int Status;

fprintf(stderr, "AFTER FORK, CHILD = %d\n", getpid());
#else

if (childpid > 0)
{ /* parent */
int deb = getpid();
int app = childpid;
int Status;

fprintf(stderr, "AFTER FORK, PARENT = %d\n", getpid());
#endif

/* wait for app to continue after fork (makes no difference) */
fprintf (stderr, "DEB=%d sleeping for a second\n", deb);
sleep(1);


/* (1) attach to application */
fprintf (stderr,
"DEB=%d: ptrace attach to APP=%d\n",
deb, app);
fflush(stderr);

if (ptrace (PTRACE_ATTACH, app, 0, 0) == -1)
{
fprintf (stderr,
"DEB=%d: PTRACE_ATTACH to %d failed, errno %d\n",
deb, app, errno);
return 0;
}

/* (2) wait for app to stop */
waitpid (app, &Status, 0);
if (WIFEXITED (Status))
{
fprintf (stderr, "*** APP EXITED already?\n");
return 0;
}

/* (3) continue the application with sigusr1.
* Expected (and pre-FC6) behavior is that since SIGUSR1 is blocked,
* app will ignore it, but app's sigwait(SIGUSR1) will return it */
fprintf (stderr,
"DEB=%d: CONT APP=%d with signal %d\n",
deb, app, SIGUSR1);
fflush(stderr);

if (ptrace (PTRACE_CONT, app, 0, SIGUSR1) == -1)
{
fprintf (stderr,
"DEB=%d: FAILED to continue APP=%d, err = %d\n",
deb, app, errno);
return 0;
}

/* normally would wait for SIGTRAP from exec here */
Msg = "DEB OK";

/* success, detach the debugger */
ptrace (PT_DETACH, app, 0, 0, 0);

fprintf (stderr, "DEB=%d looks ok\n", deb);
}
else
#ifdef CHILD_IS_DEBUGGER
{ /* child == debugger */
int deb = getpid();
int app = childpid;
int sig, return_sig;
fprintf(stderr, "AFTER FORK, PARENT = %d\n", getpid());

#else
{ /* child == app */
int deb = parentpid;
int app = getpid();
int sig, return_sig;

fprintf(stderr, "AFTER FORK, CHILD = %d\n", getpid());
#endif

/* (1) wait for SIGUSR1 from debugger to make sure it's ready */
fprintf (stderr,
"APP=%d: wait for SIGUSR1 from DEB=%d\n", app, deb);
fflush(stderr);
return_sig = sigwait (&sigset, &sig);
/* handle old behavior */
if ( sig <= 0 ) sig = return_sig;

/* normally would restore signal mask here before exec */
Msg = "APP OK";

/* normally would exec the real app here (sleep not relevant */
fprintf (stderr, "APP=%d sleeping for a second\n", app);
sleep(1);

fprintf (stderr, "APP=%d looks ok\n", app);
fprintf (stderr, "=== TEST PASSED!\n", app);
fflush(stderr);
}

return 0;
}


TIA for any insights,

...Tom
 
  


Reply

Tags
fork, kernel, ptrace


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
fc6 kinit works, pam_krb5 fails Bobism Fedora 0 01-17-2008 04:26 PM
LXer: Tips and tricks: How do I use the "xm block-attach" command to attach additiona LXer Syndicated Linux News 0 08-21-2007 01:50 AM
FC6: Attach SL Network Drive ericcarlson Fedora 1 03-31-2007 09:41 PM
FC6 installs but fails to display anything at runtime. Satadru Sengupta Linux - General 4 02-22-2007 01:13 AM
FC6 Upgrade, update then fails to boot saywot Fedora 1 10-28-2006 07:36 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 05:21 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration