On Mon, 2008-12-08 at 16:05 +0100, Denys Vlasenko wrote:
> I built 2.6.28-rc7 + utrace and sigstep.c indeed fails.
> 
> Here is the shortened version of sigstep.c.
> Looks like when we PTRACE_SINGLESTEP after raise (SIGUSR2),
> the child is left to run freely.
> 
> (Sorry about GNU indent style... utrace-tests requires that)
> 
> Can you confirm that it also fails for you on 2.6.28-rc7 + utrace
> but works on vanilla 2.6.28-rc7?

Please also test simplified version of the second test,
see below.

It appears that PTRACE_SINGLESTEP is a culprit here too,
no need to play with signals as in previous test,
it happens without any signals.

It also does not require many single-steps or forks,
for me it happens on the very first iteration.
(I removed the part which makes lots of forks).
--
vda



#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>

static pid_t child;

static void
cleanup (void)
{
  if (child > 0)
    kill (child, SIGKILL);
  child = 0;
  while (waitpid (-1, NULL, __WALL) > 0)
    continue;
}

static void
handler_fail (int signo)
{
  cleanup ();
  signal (SIGABRT, SIG_DFL);
  assert (0);
}

#define NUM_SINGLESTEPS 1
//#define NUM_SINGLESTEPS 10000
//#define NUM_FORKS     1

int main(int argc, char **argv)
{
        int i, status;
        pid_t pid;

        setbuf (stdout, NULL);
        atexit (cleanup);
        signal (SIGABRT, handler_fail);
        signal (SIGINT, handler_fail);
        signal (SIGALRM, handler_fail);
        alarm (5);

        child = fork();
        assert (child >= 0);
        if (child == 0) {
                /* child process */
                /* endless loop for singlestepping */
                while (!(child & 1))
                        child += 2;
                _exit(43); /* not reached */
        }

        errno = 0;
        ptrace(PTRACE_ATTACH, child, (void *)0, (void *)0);
        assert(!errno);
        pid = waitpid(child, &status, 0);
        assert (pid == child);
        assert (WIFSTOPPED (status));
        assert (WSTOPSIG (status) == SIGSTOP);

        for (i = 0; i < NUM_SINGLESTEPS; i++) {
                ptrace(PTRACE_SINGLESTEP, child, (void *)0, (void *)0);
                assert(!errno);
                /* Known bug in 2.6.28-rc7 + utrace patch:
                 * waitpit will block, child is running freely in an endless 
loop */
                pid = waitpid(child, &status, 0);
                assert (pid == child);
                assert (WIFSTOPPED (status));
                assert (WSTOPSIG (status) == SIGTRAP);
        }
        cleanup();
        return 0;
}


Reply via email to