This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] PR remote/19496, interrupted syscall in forking-threads-plus-bkpt


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7868401b7b63d851eea5de3b780591238d579bd1

commit 7868401b7b63d851eea5de3b780591238d579bd1
Author: Don Breazeal <donb@codesourcery.com>
Date:   Wed Mar 16 15:13:44 2016 -0700

    PR remote/19496, interrupted syscall in forking-threads-plus-bkpt
    
    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.

Diff:
---
 gdb/testsuite/ChangeLog                            |  7 ++++++
 .../gdb.threads/forking-threads-plus-breakpoint.c  | 14 ++++++++++--
 .../forking-threads-plus-breakpoint.exp            | 26 ++++++++++++----------
 3 files changed, 33 insertions(+), 14 deletions(-)

diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index aa5422b..62413b7 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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.
diff --git a/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.c b/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.c
index fc64d93..c169e18 100644
--- a/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.c
+++ b/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.c
@@ -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");
diff --git a/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp b/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp
index 3d8b308..364c5d4 100644
--- a/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp
+++ b/gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp
@@ -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)"
+	        }
 	    }
 	}
     }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]