From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5796 invoked by alias); 3 Jun 2008 21:54:01 -0000 Received: (qmail 5783 invoked by uid 22791); 3 Jun 2008 21:54:01 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 03 Jun 2008 21:53:43 +0000 Received: (qmail 23035 invoked from network); 3 Jun 2008 21:53:41 -0000 Received: from unknown (HELO orlando.local) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 3 Jun 2008 21:53:41 -0000 To: gdb@sourceware.org Subject: non-stop and current thread exiting Cc: Marc Khouzam Content-Disposition: inline From: Pedro Alves Date: Tue, 03 Jun 2008 21:54:00 -0000 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <200806032253.39575.pedro@codesourcery.com> X-IsSubscribed: yes Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2008-06/txt/msg00013.txt.bz2 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)' apply to the wrong thread, because GDB decided to switch threads on my back between `)' and `', 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