Patchwork Fix gdb.threads/process-dies-while-detaching.exp

login
register
mail settings
Submitter Pedro Alves
Date Dec. 3, 2017, 3:24 p.m.
Message ID <169c63c8-223e-e58c-eb42-a8e287e544ba@redhat.com>
Download mbox | patch
Permalink /patch/24697/
State New
Headers show

Comments

Pedro Alves - Dec. 3, 2017, 3:24 p.m.
On 11/23/2017 07:51 PM, Sergio Durigan Junior wrote:
> On Friday, November 17 2017, Pedro Alves wrote:
> 
>> 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.
> 
> I skimmed over the patch and it looks good to me, but you're the expert
> in this area here so I trust your judgement more than mine ;-)

:-)

I was going to push this as is, but I noticed that when
testing against --target_board=native-gdbserver, sometimes
I'd see this:

ERROR: Process no longer exists
ERROR: : spawn id exp9 not open
    while executing
"expect {
-i exp8 -timeout 220 
        -i $server_spawn_id
        eof {
            pass $test
            wait -i $server_spawn_id
            unset server_spawn_id
        }
        timeout {
           ..."
    ("uplevel" body line 1)
    invoked from within
"uplevel $body" NONE : spawn id exp9 not open


The problem is that:

 - inferior_spawn_id and server_spawn_id are the same when testing
   with gdbserver.
 - gdbserver exits after "detach", so we get an eof for
   $inferior_spawn_id in the loop in detach_and_expect_exit.
   That's the first "ERROR: Process no longer exists".
 - and then when we reach test_server_exit, server_spawn_id
   is already closed (because server_spawn_id==inferior_spawn_id).

To handle this, I'm making the loop in detach_and_expect_exit
use an indirect spawn id list and remove $inferior_spawn_id from
the list as soon as we got the inferior output we're expecting,
so that the "eof" is left unprocessed until we reach test_server_exit.

I'm squashing in the patch below.

From 75f48083daa998603438e71436e7268fc53aa978 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Sun, 3 Dec 2017 00:14:15 +0000
Subject: [PATCH] fix gdbserver target remote

---
 gdb/testsuite/gdb.threads/process-dies-while-detaching.exp | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

Patch

diff --git a/gdb/testsuite/gdb.threads/process-dies-while-detaching.exp b/gdb/testsuite/gdb.threads/process-dies-while-detaching.exp
index ea8f6e9..910e786 100644
--- a/gdb/testsuite/gdb.threads/process-dies-while-detaching.exp
+++ b/gdb/testsuite/gdb.threads/process-dies-while-detaching.exp
@@ -86,6 +86,14 @@  proc detach_and_expect_exit {inf_output_re test} {
 	}
     }]
 
+    # Use an indirect spawn id list, and remove inferior spawn id from
+    # the expected output as soon as it matches, so that if
+    # $inf_inferior_spawn_id is $server_spawn_id and we're testing in
+    # "target remote" mode, the eof caused by gdbserver exiting is
+    # left for the caller to handle.
+    global daee_spawn_id_list
+    set daee_spawn_id_list "$inferior_spawn_id $gdb_spawn_id"
+
     set saw_prompt 0
     set saw_inf_exit 0
     while { !$saw_prompt || ! $saw_inf_exit } {
@@ -96,14 +104,16 @@  proc detach_and_expect_exit {inf_output_re test} {
 	# first in the script that occurs anywhere in the input, so that
 	# we don't skip anything.
 	return_if_fail [gdb_test_multiple "" $test {
-	    -i "$inferior_spawn_id $gdb_spawn_id"
+	    -i daee_spawn_id_list
 	    -re "($inf_output_re)|($gdb_prompt )" {
 		if {[info exists expect_out(1,string)]} {
 		    verbose -log "saw inferior exit"
 		    set saw_inf_exit 1
+		    set daee_spawn_id_list "$gdb_spawn_id"
 		} elseif {[info exists expect_out(2,string)]} {
 		    verbose -log "saw prompt"
 		    set saw_prompt 1
+		    set daee_spawn_id_list "$inferior_spawn_id"
 		}
 		array unset expect_out
 	    }