Hello,

I've been running into a problem where a child running under strace does
not stop when it reaches raise(SIGSTOP). This was unexpected at first...
The attached program [strace-test.c] demoes this behavior,
and runs differently when being traced.

$ ./strace-test
Parent: sleeping for a while...
Parent: SUCCESS. Child killed, sig = 9

$ strace -f ./strace-test 2>/dev/null
Parent: sleeping for a while...
Child: FAIL.
Parent: FAIL. Child exited, status = 1

After quite some experimentation, I came to this, in the manual page:

       A traced process ignores SIGSTOP except on SVR4 platforms.

which I understand is a limitation coming from the way ptrace() works
under Linux?

So, I tried with SIGTSTP instead. Again, it seems a child process being
traced will not hang when doing a raise(SIGTSTP) [the signal to use can
be #defined in strace-test.c]

I've tried with

Linux hostname 2.6.26-2-amd64 #1 SMP Tue Jan 25 05:59:43 UTC 2011 x86_64 
GNU/Linux
and Debian-provided "strace -- version 4.5.17",

as well as

Linux hostname 3.0.4 #1 SMP Tue Aug 30 12:55:46 EEST 2011 i686 GNU/Linux
with latest strace, compiled from git master, commit
e73a89d99921f7b9dc3f1350a4eb97c7fdc6032a.

To summarize, is there anything I can do to have straced processes stop
on reception of a signal? If not, is it a matter of the way ptrace()
works? Then perhaps the manpage should not mention SIGSTOP only.

Thank you,
Vangelis.

-- 
Vangelis Koukis
[email protected]
OpenPGP public key ID:
pub  1024D/1D038E97 2003-07-13 Vangelis Koukis <[email protected]>
     Key fingerprint = C5CD E02E 2C78 7C10 8A00  53D8 FBFC 3799 1D03 8E97

Our greatest glory is not in never failing,
but in rising up every time we fail.
        -- Ralph Waldo Emerson
/*
 * strace-test.c
 *
 * Make sure everything works OK when strace'ing
 * a program using fork() and signals.
 *
 * Usage:
 *
 * strace -f ./strace-test 2>/dev/null
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <sys/wait.h>

#define STOP_SIGNAL SIGTSTP

int main(int argc, char *argv[])
{
	int status;
	pid_t p, waitp;

	p = fork();
	if (p < 0) {
		perror("fork");
		exit(1);
	}

	if (p == 0) {
		raise(STOP_SIGNAL);
		/* Should never reach this point */
		printf("Child: FAIL.\n");
		exit(1);
	}

	/*
	 * Father sleeps for a while and kills the child.
	 * The child should be alive when the father wakes.
	 */
	printf("Parent: sleeping for a while...\n");
	sleep(2);

	if (kill(p, SIGKILL) < 0) {
		perror("kill");
		exit(1);
	}

	waitp = wait(&status);
	assert(p == waitp);
	if (WIFEXITED(status)) {
		printf("Parent: FAIL. Child exited, status = %d\n",
			WEXITSTATUS(status));
		exit(1);
	}

	if (!WIFSIGNALED(status)) {
		printf("Parent: FAIL. Child not signaled?\n");
		exit(1);
	}

	printf("Parent: SUCCESS. Child killed, sig = %d\n",
		WTERMSIG(status));
	return 0;
}

Attachment: signature.asc
Description: Digital signature

------------------------------------------------------------------------------
Keep Your Developer Skills Current with LearnDevNow!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-d2d
_______________________________________________
Strace-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to