This is the mail archive of the gdb-patches@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]

[PATCH] Fix gdb.threads/process-dies-while-detaching.exp


I noticed [1] a test bug in gdb.threads/process-dies-while-detaching.exp.
Simplified, the test code in question looks somewhat like this:

~~~
  # Detach from a process, and ensure that it exits after detaching.
  # This relies on inferior I/O.

  proc detach_and_expect_exit {test} {

      gdb_test_multiple "detach" $test ....

      set saw_prompt 0
      set saw_inf_exit 0
      while { !$saw_prompt && !$saw_inf_exit } {
          gdb_test_multiple "" $test {
              -re "exited, status=0" {
                  set saw_inf_exit 1
              }
              -re "$gdb_prompt " {
                  set saw_prompt 1
              }
          }
      }

      pass $test
  }
~~~

The bug is in the while loop's condition.  We want to make sure we see
both the inferior output and the prompt, so the loop's test should be:

   -    while { !$saw_prompt && !$saw_inf_exit } {
   +    while { !$saw_prompt || !$saw_inf_exit } {

If we just fix that, the test starts failing though, because that
exposes a latent problem -- when called from
test_detach_killed_outside, the parent doesn't print "exited,
status=0", because in that case the child dies with a signal, and so
detach_and_expect_exit times out.  Fix it by making the parent print
"signaled, sig=9" in that case, and have the .exp expect it.

[1] I changed GDB in a way that should have made the test fail, but it
    didn't.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* gdb.threads/process-dies-while-detaching.c: Include <errno.h>
	and <string.h>.
	(parent_function): Print distinct messages when waitpid fails, or
	the child exits with a signal, or the child exits for an unhandled
	reason.
	* gdb.threads/process-dies-while-detaching.exp
	(detach_and_expect_exit): New 'inf_output_re' parameter and use
	it.  Wait for both inferior output and GDB's prompt.
	(do_detach): New parameter 'child_exit'.  Use it to compute
	expected inferior output.
	(test_detach, test_detach_watch, test_detach_killed_outside):
	Adjust to pass down the expected child exit kind.
---
 .../gdb.threads/process-dies-while-detaching.c     | 22 +++++++++--
 .../gdb.threads/process-dies-while-detaching.exp   | 43 +++++++++++++---------
 2 files changed, 44 insertions(+), 21 deletions(-)

diff --git a/gdb/testsuite/gdb.threads/process-dies-while-detaching.c b/gdb/testsuite/gdb.threads/process-dies-while-detaching.c
index eecaaed..4ba50d4 100644
--- a/gdb/testsuite/gdb.threads/process-dies-while-detaching.c
+++ b/gdb/testsuite/gdb.threads/process-dies-while-detaching.c
@@ -22,6 +22,8 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <assert.h>
+#include <errno.h>
+#include <string.h>
 
 /* This barrier ensures we only reach the initial breakpoint after all
    threads have started.  */
@@ -78,15 +80,27 @@ parent_function (pid_t child)
   alarm (300);
 
   ret = waitpid (child, &status, 0);
+
   if (ret == -1)
-    exit (1);
-  else if (!WIFEXITED (status))
-    exit (2);
-  else
+    {
+      printf ("waitpid, errno=%d (%s)\n", errno, strerror (errno));
+      exit (1);
+    }
+  else if (WIFEXITED (status))
     {
       printf ("exited, status=%d\n", WEXITSTATUS (status));
       exit (0);
     }
+  else if (WIFSIGNALED (status))
+    {
+      printf ("signaled, sig=%d\n", WTERMSIG (status));
+      exit (2);
+    }
+  else
+    {
+      printf ("unexpected, status=%x\n", status);
+      exit (3);
+    }
 }
 
 #endif
diff --git a/gdb/testsuite/gdb.threads/process-dies-while-detaching.exp b/gdb/testsuite/gdb.threads/process-dies-while-detaching.exp
index 4cba80c..ea8f6e9 100644
--- a/gdb/testsuite/gdb.threads/process-dies-while-detaching.exp
+++ b/gdb/testsuite/gdb.threads/process-dies-while-detaching.exp
@@ -72,9 +72,10 @@ proc return_if_fail { result } {
 }
 
 # Detach from a process, and ensure that it exits after detaching.
-# This relies on inferior I/O.
+# This relies on inferior I/O.  INF_OUTPUT_RE is the pattern that
+# matches the expected inferior output.
 
-proc detach_and_expect_exit {test} {
+proc detach_and_expect_exit {inf_output_re test} {
     global decimal
     global gdb_spawn_id
     global inferior_spawn_id
@@ -87,7 +88,7 @@ proc detach_and_expect_exit {test} {
 
     set saw_prompt 0
     set saw_inf_exit 0
-    while { !$saw_prompt && ! $saw_inf_exit } {
+    while { !$saw_prompt || ! $saw_inf_exit } {
 	# We don't know what order the interesting things will arrive in.
 	# Using a pattern of the form 'x|y|z' instead of -re x ... -re y
 	# ... -re z ensures that expect always chooses the match that
@@ -96,7 +97,7 @@ proc detach_and_expect_exit {test} {
 	# we don't skip anything.
 	return_if_fail [gdb_test_multiple "" $test {
 	    -i "$inferior_spawn_id $gdb_spawn_id"
-	    -re "(exited, status=0)|($gdb_prompt )" {
+	    -re "($inf_output_re)|($gdb_prompt )" {
 		if {[info exists expect_out(1,string)]} {
 		    verbose -log "saw inferior exit"
 		    set saw_inf_exit 1
@@ -130,15 +131,28 @@ proc continue_to_exit_bp {} {
 #
 # CMD indicates what to do with the parent after detaching the child.
 # Can be either "detach" to detach, or "continue", to continue to
-# exit.  If "continue", then CONTINUE_RE is the regexp to expect.
-# Defaults to normal exit output.
+# exit.
 #
-proc do_detach {multi_process cmd {continue_re ""}} {
+# CHILD_EXIT indicates how is the child expected to exit.  Can be
+# either "normal" for normal exit, or "signal" for killed with signal
+# SIGKILL.
+#
+proc do_detach {multi_process cmd child_exit} {
     global decimal
     global server_spawn_id
 
-    if {$continue_re == ""} {
+    if {$child_exit == "normal"} {
 	set continue_re "exited normally.*"
+	set inf_output_re "exited, status=0"
+    } elseif {$child_exit == "signal"} {
+	if {$multi_process} {
+	    set continue_re "exited with code 02.*"
+	} else {
+	    set continue_re "terminated with signal SIGKILL.*"
+	}
+	set inf_output_re "signaled, sig=9"
+    } else {
+	error "unhandled \$child_exit: $child_exit"
     }
 
     set is_remote [expr {[target_info exists gdb_protocol]
@@ -154,7 +168,7 @@ proc do_detach {multi_process cmd {continue_re ""}} {
 	if {$cmd == "detach"} {
 	    # Make sure that detach works and that the parent process
 	    # exits cleanly.
-	    detach_and_expect_exit "detach parent"
+	    detach_and_expect_exit $inf_output_re "detach parent"
 	} elseif {$cmd == "continue"} {
 	    # Make sure that continuing works and that the parent process
 	    # exits cleanly.
@@ -205,7 +219,7 @@ proc test_detach {multi_process cmd} {
 	# Run to _exit in the child.
 	continue_to_exit_bp
 
-	do_detach $multi_process $cmd
+	do_detach $multi_process $cmd "normal"
     }
 }
 
@@ -240,7 +254,7 @@ proc test_detach_watch {multi_process cmd} {
 	# thread individually).
 	continue_to_exit_bp
 
-	do_detach $multi_process $cmd
+	do_detach $multi_process $cmd "normal"
     }
 }
 
@@ -279,12 +293,7 @@ proc test_detach_killed_outside {multi_process cmd} {
 	# Give it some time to die.
 	sleep 2
 
-	if {$multi_process} {
-	    set continue_re "exited with code 02.*"
-	} else {
-	    set continue_re "terminated with signal SIGKILL.*"
-	}
-	do_detach $multi_process $cmd $continue_re
+	do_detach $multi_process $cmd "signal"
     }
 }
 
-- 
2.5.5


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