Hi,

There are two test cases I collected/updated those work fine
on mainline 2.6.28-rc7. But fail on 2.6.28-rc7+latest utrace patch.

$ ./sigstep
sigstep: sigstep.c:63: main: Assertion `0' failed.
sigstep: sigstep.c:86: main: Assertion `((((__extension__ (((union { __typeof(status) __in; int __i; }) { .__in = (status) }).__i))) & 0xff00) >> 8) == 5' failed.
Aborted

$ ./multi-step-same-time
To
Will hung.

Regards,
Wenji
/* 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
   arising from the use of this software.

   Permission is granted to anyone to use this software for any purpose,
   including commercial applications, and to alter it and redistribute it
   freely.  
*/

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

#define NUM_SINGLESTEPS 10000
#define NUM_FORKS       10

#define STATE_EXITED            1
#define STATE_STOPPED           2
#define STATE_UNKNOWN           3
#define STATE_ECHILD            4
#define STATE_SIGNALED          5
#define STATE_EXITED_TSIG       6
#define STATE_EXITED_ERRSTAT    7

static int do_wait(pid_t *wait_pid, int *ret_sig)
{
        int status, child_status;

        while (1) {
            status = waitpid(-1, &child_status, WUNTRACED|__WALL);
            if (status == -1) {
                if (errno == EINTR)
                    continue;
                if (errno == ECHILD) {
                    *wait_pid = (pid_t)0;
                    return STATE_ECHILD;
                }
                printf("do_wait: ERROR: waitpid() returned errno %d\n", errno);
                printf("---- Test Failed. ----\n");
                exit(1);
            }
            break;
        }
        *wait_pid = (pid_t)status;
        if (WIFEXITED(child_status)) {
            if (WIFSIGNALED(child_status))
                return STATE_EXITED_TSIG;
            if (WEXITSTATUS(child_status))
                return STATE_EXITED_ERRSTAT;
            return STATE_EXITED;
        }
        if (WIFSTOPPED(child_status)) {
            *ret_sig = WSTOPSIG(child_status);
            return STATE_STOPPED;
        }
        if (WIFSIGNALED(child_status)) {
            *ret_sig = WTERMSIG(child_status);
            return STATE_SIGNALED;
        }
        return STATE_UNKNOWN;
}

static void child_process(void)
{
        pid_t mypid;
        sleep(3);       /* wait for ptrace attach */
        while (1)       /* for singlestepping through arbitrary code */
                mypid = getpid();
}

static int forktests(void)
{
        int i, status, ret_sig;
        long pstatus;
        pid_t child, wait_pid;

        printf("forktests: pid %d\n", getpid());
        child = fork();
        if (child == -1) {
                printf("fork returned errno %d\n", errno);
                exit(1);
        }
        if (!child)
                child_process();
        sleep(1);
        printf("forktests: attaching to child %d...\n", child);
        pstatus = ptrace(PTRACE_ATTACH, child, (void *)0, (void *)0);
        if (pstatus == ~0l) {
                printf("ERROR: attach failed.  errno %d\n", errno);
                printf("---- Test failed. ----\n");
                exit(1);
        }
        status = do_wait(&wait_pid, &ret_sig);
        if (wait_pid != child) {
                printf("ERROR: Unexpected wait pid %d\n", wait_pid );
                printf("---- Test failed. ----\n");
                exit(1);
        }
        if (status != STATE_STOPPED) {
                printf("ERROR: Unexpected child state %d\n", status);
                printf("---- Test failed. ----\n");
                exit(1);
        }

        for (i = 0; i < NUM_SINGLESTEPS; i++) {
            pstatus = ptrace(
                PTRACE_SINGLESTEP, (pid_t)child, (void *)0, (void *)0);
            if (pstatus) {
                 printf("ERROR: ptrace singlstep returned %d\n", errno);
                 printf("---- Test failed. ----\n"); exit(1);
            }
            status = do_wait(&wait_pid, &ret_sig);
            if (wait_pid != child) {
                printf("ERROR: Unexpected wait pid %d\n", wait_pid );
                printf("---- Test failed. ----\n");
                exit(1);
            }
            if (status != STATE_STOPPED) {
                printf("ERROR: Unexpected child state %d\n", status);
                printf("---- Test failed. ----\n");
                exit(1);
            }
            if (ret_sig != SIGTRAP) {
                printf("ERROR: Unexpected child signal %d\n", ret_sig);
                printf("---- Test failed. ----\n");
                exit(1);
            }
        }
        status = kill(child, SIGKILL);
        if (status) {
                printf("ERROR: kill of child %d returned %d\n", child, errno);
                printf("---- Test failed. ----\n");
                exit(1);
        }
        status = do_wait(&wait_pid, &ret_sig);
        if (wait_pid != child) {
                printf("ERROR: Unexpected wait pid %d\n", wait_pid );
                printf("---- Test failed. ----\n");
                exit(1);
        }
        if (status != STATE_SIGNALED) {
                printf("ERROR: Unexpected child state %d\n", status);
                printf("---- Test failed. ----\n");
                exit(1);
        }
        if (ret_sig != SIGKILL) {
                printf("ERROR: Unexpected child signal %d\n", ret_sig);
                printf("---- Test failed. ----\n");
                exit(1);
        }
        exit(0);
}

int main(int argc, char **argv)
{
        int i, ret_sig, status;
        pid_t child, wait_pid;
        (void)argv; (void)argc;

        for (i = 0; i < NUM_FORKS; i++) {
                child = fork();
                if (child == -1) {
                        printf("main: fork returned errno %d\n", errno);
                        exit(1);
                }
                if (!child)
                        forktests();
        }
        sleep(5);
        for (i = 0; i < NUM_FORKS; i++) {
            status = do_wait(&wait_pid, &ret_sig);
            if (status != STATE_EXITED) {
                printf("ERROR: Unexpected child %d state %d\n", child, status);
                printf("---- Test failed. ----\n");
                exit(1);
            }
            printf("main: forktest pid %d exited successfully.\n", wait_pid);
        }
        printf("PASS : Test successfully completed.\n");
        exit(0);
}
/* This testcase is part of GDB, the GNU debugger.

   Copyright 2004, 2007 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

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


static volatile int done;
struct sigaction action;

static void
handler (int sig)
{
  raise(SIGUSR2);
  done = 1;
} /* handler */

int main()
{
        pid_t pid,child;
        int status;
        long l;

        child = fork ();
        assert (child >= 0);
        if (child == 0) {
                  l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
                  assert(l==0);
                  /* Set up the signal handler.  */
                  memset (&action, 0, sizeof (action));
                  action.sa_handler = handler;
                  sigaction(SIGUSR1, &action, NULL);

                  raise(SIGSTOP);
                  /* Wait.  */
                  while (!done);
                  assert(0); /* unreachable */
        }
        else {
                pid = waitpid(child, &status, 0);
                assert(pid==child);
                assert(WIFSTOPPED(status));
                assert(WSTOPSIG(status) == SIGSTOP);

                l = ptrace(PTRACE_CONT, child, 0, SIGUSR1);
                assert(l==0);

                pid = waitpid(child, &status, 0); /* stop at handler */
                assert(pid==child);
                assert(WIFSTOPPED(status));
                assert(WSTOPSIG(status) == SIGUSR2);

                l = ptrace(PTRACE_SINGLESTEP, child, 0, 0);/* step in handler */
                assert(l==0);

                /* update the value */  
                pid = waitpid(child, &status, 0);
                assert(pid==child);
                assert(WIFSTOPPED(status));
                assert(WSTOPSIG(status) == SIGTRAP);

                /* return from handler */
                l = ptrace(PTRACE_SINGLESTEP, child, 0, 0);
                assert(l==0);
       
                pid = waitpid(child, &status, 0); 
                assert(pid==child);
                assert(WIFSTOPPED(status));
                assert(WSTOPSIG(status) == SIGTRAP);

                l = ptrace(PTRACE_CONT, child, 0, SIGKILL);
                assert(l==0);

                pid = waitpid(pid, &status, 0);
                assert(child==pid);
                assert(WTERMSIG(status)==SIGKILL);
        }
return 0;
}

Reply via email to