GDB Basic command for multithreaded debugging.
Info threads |
Displays all threads currently available for debugging, each of which has a GDB-assigned ID, which is used later when the thread is manipulated. Previous * is the thread that is currently being debugged. |
Thread ID |
Toggles the thread of the currently debugged thread to the specified ID. |
Break thread_test.c:123 thread All
|
Set breakpoints on the corresponding lines in all threads |
Thread Apply ID1 ID2 command |
Have one or more threads execute GDB command commands. |
Thread Apply all command
|
Let all the debugged threads execute the GDB command. |
Set Scheduler-locking Off|on|step |
It is estimated that people who have actually used multi-threaded debugging can find that when using the step or the continue command to debug the currently debugged thread, the other threads are executed simultaneously, how to only let the debug program execute it? This requirement can be achieved with this command. Off does not lock any threads, that is, all threads are executed, which is the default value. On only the currently debugged program will execute. Step in a single step, in addition to the case of next over a function (the person familiar with the situation may know that this is actually a set breakpoint and then continue behavior), only when the front-thread will execute. |
GDB has the following support for debugging multi-threaded threads:
- Thread Generation Notification: GDB gives a hint when a new thread is generated
(GDB) R
Starting program:/root/thread
[New Thread 1073951360 (LWP 12900)]
[New Thread 1082342592 (LWP 12907)]---The following three new threads are created
[New Thread 1090731072 (LWP 12908)]
[New Thread 1099119552 (LWP 12909)]
- View Threads: Use info threads to view the threads that are running.
(GDB) Info threads
4 Thread 1099119552 (LWP 12940) 0xffffe002 in?? ()
3 Thread 1090731072 (LWP 12939) 0xffffe002 in?? ()
2 Thread 1082342592 (LWP 12938) 0xffffe002 in?? ()
* 1 Thread 1073951360 (LWP 12931) Main (argc=1, argv=0xbfffda04) at thread.c:21
(GDB)
Note that the number at the beginning of the line is the thread number assigned by GDB, which is used when switching threads.
Additionally, an asterisk at the beginning of the line identifies the currently active thread
- Toggle Thread: Use thread threadnumber to switch threadnumber to the thread number mentioned above. The following example shows switching the active thread from 1 to 4.
(GDB) Info Threads
4 Thread 1099119552 (LWP 12940) 0xffffe002 in?? ()
3 Thread 1090731072 (LWP 12939) 0xffffe002 in?? ()
2 Thread 1082342592 (LWP 12938) 0xffffe002 in?? ()
* 1 Thread 1073951360 (LWP 12931) Main (argc=1, argv=0xbfffda04) at thread.c:21
(GDB) thread 4
[Switching to Thread 4 (thread 1099119552 (LWP 12940)]) #0 0xffffe002 in?? ()
(GDB) Info Threads
* 4 Thread 1099119552 (LWP 12940) 0xffffe002 in?? ()
3 Thread 1090731072 (LWP 12939) 0xffffe002 in?? ()
2 Thread 1082342592 (LWP 12938) 0xffffe002 in?? ()
1 Thread 1073951360 (LWP 12931) Main (argc=1, argv=0xbfffda04) at thread.c:21
(GDB)
The following is directly in your thread function to set a breakpoint, and then continue to that breakpoint, generally multi-threaded, because it is running at the same time, it is best to set scheduler-locking on
In this case, only the current thread is debugged
----------------------------------------------------------------------------------------------------------- ---
Two. Actual combat film
Debug Program:
[CPP]View Plaincopy
- #include <stdio.h>
- #include <stdlib.h>
- #include <pthread.h>
- #include <unistd.h>
- void * FUN1 (void *arg1)
- {
- printf ("[Pthread1]-start\n");
- Sleep (2);
- printf ("[Pthread1]-end\n");
- Pthread_exit ((void *) NULL);
- }
- void * FUN2 (void *arg1)
- {
- printf ("[pthread2]-start\n");
- Sleep (2);
- printf ("[pthread2]-end\n");
- Pthread_exit ((void *) NULL);
- }
- int Main (void)
- {
- pthread_t Pid1, Pid2;
- void *tmp;
- printf ("[main]--start\n");
- if (pthread_create (&PID1, NULL, FUN1, NULL)) {
- Perror ("Create Pthread1 error\n");
- Exit (1);
- }
- if (pthread_create (&PID2, NULL, FUN2, NULL)) {
- Perror ("Create Pthread2 error\n");
- Exit (1);
- }
- if (Pthread_join (PID1, &tmp)) {
- Perror ("Join Pthread1 error\n");
- Exit (1);
- }
- if (Pthread_join (Pid2, &tmp)) {
- Perror ("Join Pthread2 error\n");
- Exit (1);
- }
- Sleep (2);
- printf ("[main]--end\n");
- return 0;
- }
This program has 3 threads, the main thread executes first, and then creates 2 child threads. After creating the main thread, such as child threads end, and then exit.
The order of the multithreaded procedure is unknown, but we use GDB debugging to specify the order of each thread. Take this example: After the main thread has finished creating pthread2 and pthread3, I don't know
Pthread2 first execution, or pthread3 first execution, do not know whether it is pthread2 to end first or Pthread3 first. But this time we debug, when the main thread has finished creating pthread2, first specify
Pthread2 First, debug it, and so pthread2 end, and then debug Pthread3, and finally back to debug main thread
[Plain]View Plaincopy
- (GDB) B 28 # First set breakpoints on main thread, set to create Pthread2 thread
- Breakpoint 1 at 0x4007dc:file D.C, line 28.
- if (pthread_create (&PID1, NULL, FUN1, NULL)) {
[Plain]View Plaincopy
- (GDB) Set scheduler-locking on # After creating pthread2, the execution order of the threads is variable, so we first set up scheduler, specify < single thread debug > Mode
[Plain]View Plaincopy
- (GDB) n # In this step, the PTHREAD2 thread has been created, and the main thread is stopped at the creation of the PTHREAD3 thread. Since we are single-threaded debugging, pthread2 although created, but did not execute
- [New Thread 0x7ffff7fe5700 (LWP 25412)]
- if (pthread_create (&pid2, NULL, FUN2, NULL)) {
[Plain]View Plaincopy
- (GDB) Info Thread # View thread information, now main creates a pthread2 thread, so there are two threads, we are currently debugging 1 threads (that is, the main thread, the asterisk represents the current thread)
- ID Target ID Frame
- 2 Thread 0x7ffff7fe5700 (LWP 25412) "A.out" 0x0000003bd880dd9c in __lll_lock_wait_private () from/lib64/libpthread.so. 0
- * 1 Thread 0x7ffff7fe6740 (LWP 25409) "a.out" main () at d.c:34
[Plain]View Plaincopy
- (GDB) Thread 2 # Now let's get the main thread to stop here and debug the pthread2 thread
- [Switching to Thread 2 (thread 0x7ffff7fe5700 (LWP 25412)])
[Plain]View Plaincopy
- (GDB) b 8 # pthread2 thread is executing a function, so add a breakpoint at the function
- Breakpoint 2 at 0x400778:file D.C, line 8.
[Plain]View Plaincopy
- (GDB) C # pthread2 debug to our Breakpoint
- Continuing.
Always n, put the Pthread2 Debug.
[Plain]View Plaincopy
- (GDB) n <span style= "color: #3333FF;" ><strong> </strong></span># pthread2 Execution complete
- 0x0000003bd8807cd7 in Start_thread () from/lib64/libpthread.so.0
- Missing separate Debuginfos, Use:debuginfo-install libgcc-4.7.0-4.fc17.x86_6
[Plain]View Plaincopy
- (GDB) thread 1 #这时我们跳回 main thread, to create Pthread3
- [Switching to Thread 1 (thread 0x7ffff7fe6740 (LWP 25409)])
[Plain]View Plaincopy
- (GDB) n
- [New Thread 0x7ffff77e4700 (LWP 25424)]
- if (Pthread_join (PID1, &tmp)) {
- (GDB) Thread 3
- [Switching to Thread 3 (thread 0x7ffff77e4700 (LWP 25424)])
Ditto, Debug pthraed3, then jump back to main thread
[Plain]View Plaincopy
- (GDB) Thread 1
- [Switching to Thread 1 (thread 0x7ffff7fe6740 (LWP 25409)])
- #0 Main () at d.c:39
- if (Pthread_join (PID1, &tmp)) {
At this point the main thread stops at Pthread_join, and if you continue debugging, the main thread blocks (not sure why), we set set scheduler-locking off to turn off single-threaded debugging, and then we continue to debug
The main thread is not blocked.
GDB Debug Multi-process method can refer to GDB debugging Nginx article can track a process for debugging