PR threads/18600: Inferiors left around after fork+thread spawn
authorPedro Alves <palves@redhat.com>
Wed, 22 Jul 2015 17:01:46 +0000 (18:01 +0100)
committerPedro Alves <palves@redhat.com>
Thu, 30 Jul 2015 17:52:09 +0000 (18:52 +0100)
The new gdb.threads/fork-plus-threads.exp test exposes one more
problem.  When one types "info inferiors" after running the program,
one see's a couple inferior left still, while there should only be
inferior #1 left.  E.g.:

 (gdb) info inferiors
   Num  Description       Executable
   4    process 8393      /home/pedro/bugs/src/test
   2    process 8388      /home/pedro/bugs/src/test
 * 1    <null>            /home/pedro/bugs/src/test
 (gdb) info threads

Calling prune_inferiors() manually at this point (from a top gdb) does
not remove them, because they still have inf->pid != 0 (while they
shouldn't).  This suggests that we never mourned those inferiors.

Enabling logs (master + previous patch) we see:

 ...
 WL: waitpid Thread 0x7ffff7fc2740 (LWP 9513) received Trace/breakpoint trap (stopped)
 WL: Handling extended status 0x03057f
 LHEW: Got clone event from LWP 9513, new child is LWP 9579
 [New Thread 0x7ffff37b8700 (LWP 9579)]
 WL: waitpid Thread 0x7ffff7fc2740 (LWP 9508) received 0 (exited)
 WL: Thread 0x7ffff7fc2740 (LWP 9508) exited.
    ^^^^^^^^
 [Thread 0x7ffff7fc2740 (LWP 9508) exited]
 WL: waitpid Thread 0x7ffff7fc2740 (LWP 9499) received 0 (exited)
 WL: Thread 0x7ffff7fc2740 (LWP 9499) exited.
 [Thread 0x7ffff7fc2740 (LWP 9499) exited]
 RSRL: resuming stopped-resumed LWP Thread 0x7ffff37b8700 (LWP 9579) at 0x3615ef4ce1: step=0
 ...
 (gdb) info inferiors
   Num  Description       Executable
   5    process 9508      /home/pedro/bugs/src/test
^^^^
   4    process 9503      /home/pedro/bugs/src/test
   3    process 9500      /home/pedro/bugs/src/test
   2    process 9499      /home/pedro/bugs/src/test
 * 1    <null>            /home/pedro/bugs/src/test
 (gdb)
 ...

Note the "Thread 0x7ffff7fc2740 (LWP 9508) exited." line.
That's this in wait_lwp:

      /* Check if the thread has exited.  */
      if (WIFEXITED (status) || WIFSIGNALED (status))
{
  thread_dead = 1;
  if (debug_linux_nat)
    fprintf_unfiltered (gdb_stdlog, "WL: %s exited.\n",
target_pid_to_str (lp->ptid));
}
    }

That was the leader thread reporting an exit, meaning the whole
process is gone.  So the problem is that this code doesn't understand
that an WIFEXITED status of the leader LWP should be reported to
infrun as process exit.

gdb/ChangeLog:
2015-07-30  Pedro Alves  <palves@redhat.com>

PR threads/18600
* linux-nat.c (wait_lwp): Report to the core when thread group
leader exits.

gdb/testsuite/ChangeLog:
2015-07-30  Pedro Alves  <palves@redhat.com>

PR threads/18600
* gdb.threads/fork-plus-threads.exp: Test that "info inferiors"
only shows inferior 1.

gdb/ChangeLog
gdb/linux-nat.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.threads/fork-plus-threads.exp

index 40403f9c90094d7553b76fd22ad4bbf56109b16f..64fbe8e55b914ea6101a4571e9fc554a91aff1f4 100644 (file)
@@ -1,3 +1,9 @@
+2015-07-30  Pedro Alves  <palves@redhat.com>
+
+       PR threads/18600
+       * linux-nat.c (wait_lwp): Report to the core when thread group
+       leader exits.
+
 2015-07-30  Pedro Alves  <palves@redhat.com>
            Simon Marchi  <simon.marchi@ericsson.com>
 
index 966c6a88e9b29f33fb877dd6c93d5c0b21f69bbb..69cfefcae3b0a1fc5b219ac9dd68ee8953c3592b 100644 (file)
@@ -2274,6 +2274,20 @@ wait_lwp (struct lwp_info *lp)
       /* Check if the thread has exited.  */
       if (WIFEXITED (status) || WIFSIGNALED (status))
        {
+         if (ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid))
+           {
+             if (debug_linux_nat)
+               fprintf_unfiltered (gdb_stdlog, "WL: Process %d exited.\n",
+                                   ptid_get_pid (lp->ptid));
+
+             /* This is the leader exiting, it means the whole
+                process is gone.  Store the status to report to the
+                core.  Store it in lp->waitstatus, because lp->status
+                would be ambiguous (W_EXITCODE(0,0) == 0).  */
+             store_waitstatus (&lp->waitstatus, status);
+             return 0;
+           }
+
          thread_dead = 1;
          if (debug_linux_nat)
            fprintf_unfiltered (gdb_stdlog, "WL: %s exited.\n",
index 06ca98797b04b8014b40a11af96c474a7b28e989..e3126edab1cb78a2a942709e9ba3b737e2141144 100644 (file)
@@ -1,3 +1,9 @@
+2015-07-30  Pedro Alves  <palves@redhat.com>
+
+       PR threads/18600
+       * gdb.threads/fork-plus-threads.exp: Test that "info inferiors"
+       only shows inferior 1.
+
 2015-07-30  Simon Marchi  <simon.marchi@ericsson.com>
            Pedro Alves  <palves@redhat.com>
 
index 53d110224db1154d73b761bb9f6a7e7c0532358b..8a503ec6c84f714367c236a0dbadea371837339e 100644 (file)
@@ -60,6 +60,10 @@ proc do_test { detach_on_fork } {
 
     gdb_test "info threads" "No threads\." \
        "no threads left"
+
+    gdb_test "info inferiors" \
+       "Num\[ \t\]+Description\[ \t\]+Executable\[ \t\]+\r\n\\* 1 \[^\r\n\]+" \
+       "only inferior 1 left"
 }
 
 foreach detach_on_fork {"on" "off"} {