Two test cases

Denys Vlasenko dvlasenk at redhat.com
Mon Dec 8 15:05:07 UTC 2008


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;
}





More information about the utrace-devel mailing list