As part of its Java-related projects, Silicomp Research Institute has made the required enhancements to gdb-4.17 to debug GNU/Linux multithreaded applications. The basic Linus Torvald's intuition that "all we need in the kernel is clone()" has been kept within this development, and all the work done by GDB is made at user level. Therefore, no Linux kernel extension is needed and all tests have been made on a standard Linux-2.0.32 kernel.
By looking into the debugged process memory, GDB scans the internal structures of the LinuxThreads and is able to report all threads status to its standard user interface. There is always one current thread which reports an event to the user interface, and the command typed by the user always apply to the current thread. But it is always possible to switch current thread with another and to apply commands to the new one.
The main problem with this architecture is that the internal structures of the LinuxThreads are assumed to be never broken by any user program, in which cases GDB may report permanent errors that may require GDB and the application threads to be killed by hand; fortunately, these cases remain very unfrequent.
Before the first thread is created, there is no difference in the behaviour of GDB with a single-threaded program; but as soon as it is created, GDB switches into a multithreaded mode which allows to get access to thread-related commands (see your GDB manual). In the list of threads, the thread number 1 is the LinuxThreads internal manager thread and never executes user code. It should be ignored when an application is debugged, and only be used when the LinuxThreads library is itself debugged.
There are two new messages that will appear asynchronously on the screen:
The different threads have completely independent behaviour from a debugging point of view. This means that when an event has to be reported for a current thread, GDB scans the thread list and stops individually each of them, thus introducing asynchronism between them (the status reported for non-current threads is the one that may have occured long after the time of the current one). The primary consequence is that more than one thread may have hit breakpoints at a given time, but only the first one is reported at the beginning. As soon as a continuation command is reported, then event of other threads can be reported safely to the user.
A multithreaded application can be run directly from inside GDB, or attached dynamically by the PID of any application thread. GDB will first stop the LinuxThreads manager (thus stopping any new thread from being created), and then all others before the application threads can be analyzed. The intr character (usually ^C) can be hit in the start window of the application in order to stop it. But, if it has been dynamically attached by GDB, it will receive as many SIGINTR signals as there are application threads, since it is the kernel standard behaviour (which is not the case for processes run within GDB).
As part of the LinuxThreads debugging patches, there are two other enhancements included that are specific to the the i386 target:
There are two patch files that are required to be applied in order to access to the Linux multithreading enhancements of GDB:
Although most of this stuff should be machine-independent, all the code available for GDB has only been tested on Linux-2.0.32 for i386 uniprocessor systems. Nobody has yet reported that it worked on other targets, nor on i386 multiprocessor systems.
In the same idea, the only multithreaded programs that have been debugged with GDB have been written in C programming language. Opinion of people having debugged multithreaded programs written in other programming languages (like C++) is welcome.
Discussion on the LinuxThreads debugging is welcome in the regular places where LinuxThreads are discussed: either in the newsgroup comp.programming.threads or in the mailing list [email protected] (which you can subscribe to by writing at [email protected]).