PR remote/19496, interrupted syscall in forking-threads-plus-bkpt
authorDon Breazeal <donb@codesourcery.com>
Wed, 16 Mar 2016 22:13:44 +0000 (15:13 -0700)
committerDon Breazeal <donb@codesourcery.com>
Wed, 16 Mar 2016 22:13:44 +0000 (15:13 -0700)
This patch addresses "fork:Interrupted system call" (or wait:) failures
in gdb.threads/forking-threads-plus-breakpoint.exp.

The test program spawns ten threads, each of which do ten fork/waitpid
sequences.  The cause of the problem was that when one of the fork
children exited before the corresponding fork parent could initiate its
waitpid for that child, a SIGCHLD and/or SIGSTOP was delivered and
interrupted a fork or waitpid in another thread.

The fix was to wrap the system calls in a loop to retry the call if
it was interrupted, like:

do
  {
    pid = fork ();
  }
while (pid == -1 && errno == EINTR);

Since this is a Linux-only test I figure it is OK to use errno and EINTR.
I tried a number of alternative fixes using SIG_IGN, SA_RESTART,
pthread_sigblock, and bsd_signal, but none of these worked as well.

Tested on Nios II Linux target with x86 Linux host.

gdb/testsuite/ChangeLog:
2016-03-16  Don Breazeal  <donb@codesourcery.com>

* gdb.threads/forking-threads-plus-breakpoint.c (thread_forks):
Retry fork and waitpid on interrupted system call errors.
* gdb.threads/forking-threads-plus-breakpoint.exp: (do_test):
Use with_timeout_factor to increase timeout to 90.

gdb/testsuite/ChangeLog
gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.c
gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp

index aa5422b64043d138232af48742867db6b504dff5..62413b73f113888cda03973a5e0a3cb8d47426d3 100644 (file)
@@ -1,3 +1,10 @@
+2016-03-16  Don Breazeal  <donb@codesourcery.com>
+
+       * gdb.threads/forking-threads-plus-breakpoint.c (thread_forks):
+       Retry fork and waitpid on interrupted system call errors.
+       * gdb.threads/forking-threads-plus-breakpoint.exp (do_test):
+       Use with_timeout_factor to increase timeout by factor of 10.
+
 2016-03-15  Don Breazeal  <donb@codesourcery.com>
 
        * gdb.cp/scope-err.cc: New test program.
index fc64d93cc01018988b3c1633a4021a8ada6b2a44..c169e18d0b8b6df56180be08fb97be5f460c2dba 100644 (file)
@@ -22,6 +22,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <stdlib.h>
+#include <errno.h>
 
 /* Number of threads.  Each thread continuously spawns a fork and wait
    for it.  If we have another thread continuously start a step over,
@@ -49,14 +50,23 @@ thread_forks (void *arg)
     {
       pid_t pid;
 
-      pid = fork ();
+      do
+       {
+         pid = fork ();
+       }
+      while (pid == -1 && errno == EINTR);
 
       if (pid > 0)
        {
          int status;
 
          /* Parent.  */
-         pid = waitpid (pid, &status, 0);
+         do
+           {
+             pid = waitpid (pid, &status, 0);
+           }
+         while (pid == -1 && errno == EINTR);
+
          if (pid == -1)
            {
              perror ("wait");
index 3d8b3080cc79986272864b3eaa148498840e35b2..364c5d48a883966f8dc0c34f257eee51b8e8e5b9 100644 (file)
@@ -115,18 +115,20 @@ proc do_test { cond_bp_target detach_on_fork displaced } {
     set fork_count 0
     set ok 0
 
-    set test "inferior 1 exited"
-    gdb_test_multiple "" $test {
-       -re "Inferior 1 \(\[^\r\n\]+\) exited normally" {
-           set ok 1
-           pass $test
-       }
-       -re "Inferior $decimal \(\[^\r\n\]+\) exited normally" {
-           incr fork_count
-           if {$fork_count <= 100} {
-               exp_continue
-           } else {
-               fail "$test (too many forks)"
+    with_timeout_factor 10 {
+        set test "inferior 1 exited"
+        gdb_test_multiple "" $test {
+           -re "Inferior 1 \(\[^\r\n\]+\) exited normally" {
+               set ok 1
+               pass $test
+           }
+           -re "Inferior $decimal \(\[^\r\n\]+\) exited normally" {
+               incr fork_count
+               if {$fork_count <= 100} {
+                   exp_continue
+               } else {
+                   fail "$test (too many forks)"
+               }
            }
        }
     }