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

non-stop and current thread exiting


Hi all,

Non-stop has currently one issue to resolve that I'd like
your input on.

With all stop, no command is allowed while the inferior is running.
In sync mode, well, GDB isn't listenning to commands, in async mode,
only a few commands are allowed, I think help, interrupt, dir, pwd,
not much else.  These are all commands safe to use.

Imagine the case where you're debugging a multi-threaded app.  There
are 3 threads including the main thread.
Thread 2 is selected.   You issue continue, that thread exits, but
GDB doesn't give the user the control then, the inferior is kept running.
Finally, when some other thread hits a breakpoint GDB switches the
user thread to it automatically.  Hence, there was never a situation
where the selected thread has already exited, on which case the user
could issue commands to a dead thread.

Now, enter non-stop.  With non-stop, however, we'll want to be
able to say for example "info threads" at any time (or -thread-info,
in MI).

Take this example:

 (gdb)l
 75          volatile int *myp = (volatile int *) &args[my_number];
 76
 77          /* Don't run forever.  Run just short of it :)  */
 78          while (*myp > 0)
 79            {
 80              (*myp) ++;
 81              usleep (1);  /* Loop increment.  */
 82              //      printf ("thread_function1: %d\n", *myp);
 83              //      fflush (stdout);
 84            }
 (gdb)l
 85
 86          pthread_exit(NULL);
 87      }

 (gdb) b 80
 Breakpoint 1 at 0x80485f0: file threads.c, line 80.
 (gdb) r

 Starting program: /home/pedro/gdb/tests/threads32
 [Thread debugging using libthread_db enabled]
 [New Thread 0xf7d5bb90 (LWP 8506)]
 [New Thread 0xf755ab90 (LWP 8507)]
 [Switching to Thread 0xf755ab90 (LWP 8507)]

 Breakpoint 1, thread_function1 (arg=0x1) at threads.c:80
 80              (*myp) ++;

 (gdb) n&
 (gdb) 81                usleep (1);  /* Loop increment.  */

Now, let's let the selected thread exit.

 p *myp=0
 $1 = 0
 (gdb) c&
 Continuing.
 (gdb) [Thread 0xf755ab90 (LWP 8507) exited]

At this point, which should be the selected thread,
and what should "info threads" show?

GDB isn't currently prepared for this situation,
so with the last non-stop series I posted, several 
commands issued at this point trigger internal
assertions, because the current thread doesn't exist
in the thread list.

I see three possibilities to solve issues like these.

a) Have GDB switch to an arbitrary thread when the
  current thread is gone.

b) Leave the currently selected dead thread in the thread
  list, tag it as dead.  Prohibit most commands but "thread"
  and "info threads" in this situation.  Get rid of the dead
  thread as soon as the user/frontend switches to another
  thread.

 (gdb) info threads
 * 3 Thread 0xf755ab90 (LWP 8507)  (exited)
   2 Thread 0xf7d5bb90 (LWP 8506)  (running)
   1 Thread 0xf7d5c6b0 (LWP 8503)  (running)

Notice the "(exited)" mark.

 (gdb) print a
 The selected thread is no longer available.  See `help thread'
 to change selected thread.

Switching threads:

 (gdb) thread 2
 [Switching to thread 2 (Thread 0xf7ddfb90 (LWP 10771))] (running)

Ah, it's gone now:

 (gdb) info threads
 * 2 Thread 0xf7ddfb90 (LWP 10771)  (running)
   1 Thread 0xf7de06b0 (LWP 10766)  (running)


c) Allow deleting the current thread anyway, and have it not
   listed in the thread list.  Do some internal magic, to point
   the current thread at some "already exited" special thread.
   Prohibit most commands but "thread" and "info threads" in
   this situation.  Show something like this or similar
   in "info threads"

 (gdb) info threads
   2 Thread 0xf7d5bb90 (LWP 8506)  (running)
   1 Thread 0xf7d5c6b0 (LWP 8503)  (running)

   No selected thread.

I like b) or c) because I prefer that GDB doesn't switch
threads on me automatically.  Having 'call ExitThread (1)<enter>'
apply to the wrong thread, because GDB decided to switch threads
on my back between `)' and `<enter>', is a race I'd like to avoid.

b) has the disadvantage that code that iterates over threads may
  have to take care of not doing things to dead threads.  I don't
  think there are many places.
  It has the advantage that the user can still see some info
  on which thread was last selected.

c) has the advantage that code that iterates over threads, can still
   rely on a thread being ptid(-1) to mean it's dead.  Easier to
   spot a bug.  We can perhaps still show to the user which thread
   was selected by storing that info in some global:

   2 Thread 0xf7d5bb90 (LWP 8506)  (running)
   1 Thread 0xf7d5c6b0 (LWP 8503)  (running)

   The selected thread was 3, but it has exited.  Please 
   change threads.


We had a small internal discussion, and at the time there was
concensus that b) would be the best option.

What do you think?  Do you see other options, or problems
with b) ?

Marc, could you share with us your thoughts, in the
perspective of a non-stop frontend developer ?

-- 
Pedro Alves


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