]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Refactor and recomment async-sigs so it's easier to understand. Send all
authorNicholas Nethercote <njn@valgrind.org>
Fri, 1 May 2009 05:00:34 +0000 (05:00 +0000)
committerNicholas Nethercote <njn@valgrind.org>
Fri, 1 May 2009 05:00:34 +0000 (05:00 +0000)
its output to stderr as well.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@9706

none/tests/Makefile.am
none/tests/async-sigs.c
none/tests/async-sigs.stderr.exp
none/tests/async-sigs.stdout.exp [deleted file]
none/tests/async-sigs.vgtest

index 4f71ffbe1f535a85b035e859cb378721bbccc830..f1bbff6cad0cef1ac6b8180bd84f3d572926b4aa 100644 (file)
@@ -38,7 +38,7 @@ noinst_HEADERS = fdleak.h
 EXTRA_DIST = $(noinst_SCRIPTS) \
        ansi.stderr.exp ansi.vgtest \
        args.stderr.exp args.stdout.exp args.vgtest \
-       async-sigs.stderr.exp async-sigs.stdout.exp async-sigs.vgtest \
+       async-sigs.stderr.exp async-sigs.vgtest \
        bitfield1.stderr.exp bitfield1.vgtest \
        bug129866.vgtest bug129866.stderr.exp bug129866.stdout.exp \
        closeall.stderr.exp closeall.vgtest \
index 3e403f6d00322072e440ac48d32a19a2d3fb96fb..25b730bef0e1512bc2b05db5bb4c9e547deaa76f 100644 (file)
@@ -1,3 +1,12 @@
+// This tests handling of signals sent from outside the process in the
+// following combinations:  sync and async signals, caught and uncaught
+// signals, and while blocking or not blocking in a syscall.  This exercises
+// various different paths in Valgrind's signal handling.
+//
+// It does this by installing signal handlers for one signal S, spawning
+// another process P, sending S from P multiple times (all caught), then
+// sending another signal from P (not caught).
+
 #include <signal.h>
 #include <unistd.h>
 #include <sys/wait.h>
@@ -7,7 +16,7 @@
 #include <errno.h>
 #include <time.h>
 
-static const struct timespec bip = { 0, 1000000000 / 5 };
+static const struct timespec bip = { 0, 1000000000 / 5 };   // 0.2 seconds.
 
 static void handler(int sig)
 {
@@ -18,103 +27,113 @@ static void handler(int sig)
    respect to thread scheduling. */
 static void do_kill(int pid, int sig)
 {
-       int status;
-       int killer;
-       int ret;
-
-       killer = vfork();
-       
-       if (killer == -1) {
-               perror("killer/vfork");
-               exit(1);
-       }
-
-       if (killer == 0) {
-               char sigbuf[20];
-               char pidbuf[20];
-               sprintf(sigbuf, "-%d", sig);
-               sprintf(pidbuf, "%d", pid);
-               execl("/bin/kill", "kill", sigbuf, pidbuf, NULL);
-               perror("exec failed");
-               exit(1);
-       }
-
-       do 
-               ret = waitpid(killer, &status, 0);
-       while(ret == -1 && errno == EINTR);
-
-       if (ret != killer) {
-               perror("kill/waitpid");
-               exit(1);
-       }
-
-       if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
-               printf("kill %d failed status=%s %d\n", killer, 
-                      WIFEXITED(status) ? "exit" : "signal", 
-                      WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status));
-               exit(1);
-       }
+   int status;
+   int killer;
+   int ret;
+
+   killer = vfork();
+   if (killer == -1) {
+      perror("killer/vfork");
+      exit(1);
+   }
+
+   // In the child, exec 'kill' in order to send the signal.
+   if (killer == 0) {
+      char sigbuf[20];
+      char pidbuf[20];
+      sprintf(sigbuf, "-%d", sig);
+      sprintf(pidbuf, "%d", pid);
+      execl("/bin/kill", "kill", sigbuf, pidbuf, NULL);
+      perror("exec failed");
+      exit(1);
+   }
+
+   // In the parent, just wait for the child and then check it ran ok.
+   do 
+      ret = waitpid(killer, &status, 0);
+   while (ret == -1 && errno == EINTR);
+
+   if (ret != killer) {
+      perror("kill/waitpid");
+      exit(1);
+   }
+
+   if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+      fprintf(stderr, "kill %d failed status=%s %d\n", killer, 
+             WIFEXITED(status) ? "exit" : "signal", 
+             WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status));
+      exit(1);
+   }
 }
 
 static void test(int block, int caughtsig, int fatalsig)
 {
-       int pid;
-       int status;
-       int i;
-
-       printf("testing: blocking=%d caught=%d fatal=%d... ", block, caughtsig, fatalsig);
-       fflush(stdout);
-
-       pid = fork();
-       if (pid == -1) {
-               perror("fork");
-               exit(1);
-       }
-
-       if (pid == 0) {
-         alarm(10); /* if something breaks, don't spin forever */
-               signal(caughtsig, handler);
-
-               for(;;)
-                       if (block)
-                               pause();
-
-       }
-
-       nanosleep(&bip, 0);             /* wait for child to get going */
-
-       for(i = 0; i < 5; i++) {
-               do_kill(pid, caughtsig);        /* should be caught */
-               nanosleep(&bip, 0);
-               do_kill(pid, caughtsig);
-               do_kill(pid, caughtsig);
-       }
-
-       nanosleep(&bip, 0);
-
-       do_kill(pid, fatalsig); /* should kill it */
-       
-       if (waitpid(pid, &status, 0) != pid)
-               printf("FAILED: waitpid failed: %s\n", strerror(errno));
-       else if (!WIFSIGNALED(status) || WTERMSIG(status) != fatalsig)
-               printf("FAILED: child exited with unexpected status %s %d\n",
-                      WIFEXITED(status) ? "exit" : "signal", 
-                      WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status));
-       else
-               printf("PASSED\n");
+   int pid;
+   int status;
+   int i;
+
+   fprintf(stderr, "testing: blocking=%d caught=%d fatal=%d... ",
+      block, caughtsig, fatalsig);
+
+   pid = fork();
+   if (pid == -1) {
+      perror("fork");
+      exit(1);
+   }
+
+   // In the child, install the signal handler, then wait for the signal to
+   // arrive:
+   // - if 'block' is set, wait on a system call;
+   // - otherwise, wait in client code (by spinning).
+   // The alarm() calls is so that if something breaks, we don't get stuck.
+   if (pid == 0) {
+      signal(caughtsig, handler);
+      alarm(10);
+
+      for (;;)
+         if (block) {
+            pause();
+         }
+   }
+
+   // In the parent, send the signals.
+   nanosleep(&bip, 0);           // Wait for child to get going.
+
+   for (i = 0; i < 5; i++) {
+      do_kill(pid, caughtsig);   // Should be caught.
+      nanosleep(&bip, 0);
+      do_kill(pid, caughtsig);   // Ditto.
+      do_kill(pid, caughtsig);   // Ditto.
+   }
+
+   nanosleep(&bip, 0);
+
+   do_kill(pid, fatalsig);       // Should kill it.
+   
+   // Check that the child behaved as expected when it received the signals.
+   if (waitpid(pid, &status, 0) != pid) {
+      fprintf(stderr, "FAILED: waitpid failed: %s\n", strerror(errno));
+
+   } else if (!WIFSIGNALED(status) || WTERMSIG(status) != fatalsig) {
+      fprintf(stderr, "FAILED: child exited with unexpected status %s %d\n",
+             WIFEXITED(status) ? "exit" : "signal", 
+             WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status));
+
+   } else {
+      fprintf(stderr, "PASSED\n");
+   }
 }
 
 int main()
 {
-       static const int catch[] = { SIGSEGV, SIGUSR1 };
-       static const int fatal[] = { SIGBUS, SIGUSR2 };
-       int block, catchidx, fatalidx;
-
-       setvbuf(stdout, NULL, _IOLBF, 0);
-       
-       for(block = 0; block < 2; block++)
-               for(catchidx = 0; catchidx < sizeof(catch)/sizeof(*catch); catchidx++)
-                       for(fatalidx = 0; fatalidx < sizeof(fatal)/sizeof(*fatal); fatalidx++)
-                               test(block, catch[catchidx], fatal[fatalidx]);
-       return 0;
+   test(/*non-blocked*/0, /* sync*/SIGSEGV, /* sync*/SIGBUS);
+   test(/*non-blocked*/0, /* sync*/SIGSEGV, /*async*/SIGHUP);
+   test(/*non-blocked*/0, /*async*/SIGUSR1, /* sync*/SIGBUS);
+   test(/*non-blocked*/0, /*async*/SIGUSR1, /*async*/SIGHUP);
+   test(/*    blocked*/1, /* sync*/SIGSEGV, /* sync*/SIGBUS);
+   test(/*    blocked*/1, /* sync*/SIGSEGV, /*async*/SIGHUP);
+   test(/*    blocked*/1, /*async*/SIGUSR1, /* sync*/SIGBUS);
+   test(/*    blocked*/1, /*async*/SIGUSR1, /*async*/SIGHUP);
+
+   return 0;
 }
index 584ba8795fb2d9b8051bc199333bd273af380dca..6e784a2ef740c90a39cdf971077c1959c8e7d134 100644 (file)
@@ -1,10 +1,8 @@
-
-
-
-
-
-
-
-
-
-
+testing: blocking=0 caught=11 fatal=7... PASSED
+testing: blocking=0 caught=11 fatal=1... PASSED
+testing: blocking=0 caught=10 fatal=7... PASSED
+testing: blocking=0 caught=10 fatal=1... PASSED
+testing: blocking=1 caught=11 fatal=7... PASSED
+testing: blocking=1 caught=11 fatal=1... PASSED
+testing: blocking=1 caught=10 fatal=7... PASSED
+testing: blocking=1 caught=10 fatal=1... PASSED
diff --git a/none/tests/async-sigs.stdout.exp b/none/tests/async-sigs.stdout.exp
deleted file mode 100644 (file)
index 397f499..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-testing: blocking=0 caught=11 fatal=7... PASSED
-testing: blocking=0 caught=11 fatal=12... PASSED
-testing: blocking=0 caught=10 fatal=7... PASSED
-testing: blocking=0 caught=10 fatal=12... PASSED
-testing: blocking=1 caught=11 fatal=7... PASSED
-testing: blocking=1 caught=11 fatal=12... PASSED
-testing: blocking=1 caught=10 fatal=7... PASSED
-testing: blocking=1 caught=10 fatal=12... PASSED
index 6a6a77dae9e6c52a32eac7d09e9d79ad24e27a29..ec51f036fdebbe8b45d328d31731ae2ec9d89902 100644 (file)
@@ -1 +1,2 @@
 prog: async-sigs
+vgopts: -q