On Mon, 2008-12-08 at 14:22 +0100, Denys Vlasenko wrote: > On Mon, 2008-12-08 at 10:40 +0800, Wenji Huang wrote: > > Denys Vlasenko wrote: > > > On Fri, 2008-12-05 at 11:10 +0800, Wenji Huang wrote: > > >> 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.c has "This testcase is part of GDB, the GNU debugger." > comment. And gdb indeed has sigstep.c file. But it does not > seem to have much in common with your sigstep.c. > > multi-step-same-time.c does not seem to be from GDB. > > Therefore they are not an established, known-to-work testcases > (at least I can't find where they come from), they are just some > C programs which work on vanilla kernel and fail on utrace. > > This means that they need to pass through a review before > we can assume the problem is in utrace and not in the tests. > > And this means that you need to explain unclear moments, > and tweak parts of tests where they do not seem to be doing > the right thing(s), or are simply superfluous. > > At least that's how I understand the situation. > Do you see it the same? I'm asking because you did not provide > a tweaked (shortened?) version of sigstep.c in your reply, > which I sort-of-expected. > Do you want someone else to do it?
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? -- vda #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 void handler (int sig) { raise (SIGUSR2); sig += 42; /* ensure there are some instructions prior to exit */ _exit (sig); /* not reached */ } /* If nothing strange happens, just return 0. * Known bugs exit with 1. * New bugs are likely to trip asserts. */ int main (int argc, char **argv) { pid_t pid, child; int status; long l; child = fork (); assert (child >= 0); if (child == 0) { signal (SIGUSR1, handler); l = ptrace (PTRACE_TRACEME, 0, (char *) 0, (char *) 0); assert (l == 0); raise (SIGSTOP); _exit (43); /* not reached */ } pid = waitpid (child, &status, 0); assert (pid == child); assert (WIFSTOPPED (status)); assert (WSTOPSIG (status) == SIGSTOP); /* Inject SIGUSR1, unpause */ l = ptrace (PTRACE_CONT, child, (char *) 0, (char *) SIGUSR1); assert (l == 0); /* Expect to catch SIGUSR2 thrown from the SIGUSR1 handler */ pid = waitpid (child, &status, 0); assert (pid == child); assert (WIFSTOPPED (status)); assert (WSTOPSIG (status) == SIGUSR2); /* Step one instruction after raise(SIGUSR2) in handler */ /* (do NOT reinject SIGUSR2) */ l = ptrace (PTRACE_SINGLESTEP, child, (char *) 0, (char *) 0); assert (l == 0); /* Expect SIGTRAP */ pid = waitpid (child, &status, 0); assert (pid == child); /* Known bug in 2.6.28-rc7 + utrace patch: * child's signal handler was left to run freely, and exited */ if (WIFEXITED (status)) { assert (WEXITSTATUS (status) == (SIGUSR1 + 42)); return 1; } assert (WIFSTOPPED (status)); assert (WSTOPSIG (status) == SIGTRAP); kill (child, SIGKILL); return 0; }