4.3.5. Debugging Individual Threads GDB has the ability to debug individual threads, and to manipulate and examine them independently. This functionality is not enabled by default. To do so use set non-stop on and set target-async on . These can be added to .gdbinit . Once that functionality is turned on, GDB is ready to conduct thread debugging. For example, the following program creates two threads. These two threads, along with the original thread executing main makes a total of three threads. three-threads.c #include <stdio.h> #include <pthread.h> #include <unistd.h> pthread_t thread; void* thread3 (void* d) { int count3 = 0; while(count3 < 1000){ sleep(10); printf("Thread 3: %d\n", count3++); } return NULL; } void* thread2 (void* d) { int count2 = 0; while(count2 < 1000){ printf("Thread 2: %d\n", count2++); } return NULL; } int main (){ pthread_create (&thread, NULL, thread2, NULL); pthread_create (&thread, NULL, thread3, NULL); //Thread 1 int count1 = 0; while(count1 < 1000){ printf("Thread 1: %d\n", count1++); } pthread_join(thread,NULL); return 0; } Compile this program in order to examine it under GDB. gcc -g three-threads.c -o three-threads -lpthread gdb ./three-threads First set breakpoints on all thread functions; thread1, thread2, and main. (gdb) break thread3 Breakpoint 1 at 0x4006c0: file three-threads.c, line 9. (gdb) break thread2 Breakpoint 2 at 0x40070c: file three-threads.c, line 20. (gdb) break main Breakpoint 3 at 0x40074a: file three-threads.c, line 30. Then run the program. (gdb) run [...] Breakpoint 3, main () at three-threads.c:30 30 pthread_create (&thread, NULL, thread2, NULL); [...] (gdb) info threads * 1 Thread 0x7ffff7fd5720 (LWP 4620) main () at three-threads.c:30 (gdb) Note that the command info threads provides a summary of the program's threads and some details about their current state. In this case there is only one thread that has been created so far. Continue execution some more. (gdb) [New Thread 0x7ffff7fd3710 (LWP 4687)] 31 pthread_create (&thread, NULL, thread3, NULL); (gdb) Breakpoint 2, thread2 (d=0x0) at three-threads.c:20 20 int count2 = 0; [New Thread 0x7ffff75d2710 (LWP 4688)] 34 int count1 = 0; (gdb) Breakpoint 1, thread3 (d=0x0) at three-threads.c:9 9 int count3 = 0; info threads 3 Thread 0x7ffff75d2710 (LWP 4688) thread3 (d=0x0) at three-threads.c:9 2 Thread 0x7ffff7fd3710 (LWP 4687) thread2 (d=0x0) at three-threads.c:20 * 1 Thread 0x7ffff7fd5720 (LWP 4620) main () at three-threads.c:34 Here, two more threads are created. The star indicates the thread currently under focus. Also, the newly created threads have hit the breakpoint set for them in their initialization functions. Namely, thread2() and thread3(). To begin real thread debugging, use the thread <thread number> command to switch the focus to another thread. (gdb) thread 2 [Switching to thread 2 (Thread 0x7ffff7fd3710 (LWP 4687))]#0 thread2 (d=0x0) at three-threads.c:20 20 int count2 = 0; (gdb) list 15 return NULL; 16 } 17 18 void* thread2 (void* d) 19 { 20 int count2 = 0; 21 22 while(count2 < 1000){ 23 printf("Thread 2: %d\n", count2++); 24 } Thread 2 stopped at line 20 in its function thread2(). (gdb) 22 while(count2 < 1000){ (gdb) print count2 USD1 = 0 (gdb) 23 printf("Thread 2: %d\n", count2++); (gdb) Thread 2: 0 22 while(count2 < 1000){ (gdb) 23 printf("Thread 2: %d\n", count2++); (gdb) print count2 USD2 = 1 (gdb) info threads 3 Thread 0x7ffff75d2710 (LWP 4688) thread3 (d=0x0) at three-threads.c:9 * 2 Thread 0x7ffff7fd3710 (LWP 4687) thread2 (d=0x0) at three-threads.c:23 1 Thread 0x7ffff7fd5720 (LWP 4620) main () at three-threads.c:34 (gdb) Above, a few lines of thread2 printed the counter count2 and left thread 2 at line 23 as is seen by the output of 'info threads'. Now thread3. (gdb) thread 3 [Switching to thread 3 (Thread 0x7ffff75d2710 (LWP 4688))]#0 thread3 (d=0x0) at three-threads.c:9 9 int count3 = 0; (gdb) list 4 5 pthread_t thread; 6 7 void* thread3 (void* d) 8 { 9 int count3 = 0; 10 11 while(count3 < 1000){ 12 sleep(10); 13 printf("Thread 3: %d\n", count3++); (gdb) Thread three is a little different in that it has a sleep statement and executes slowly. Think of it as a representation of an uninteresting IO thread. Because this thread is uninteresting, continue its execution uninterrupted, using the continue . (gdb) continue & (gdb) Thread 3: 0 Thread 3: 1 Thread 3: 2 Thread 3: 3 Take note of the & at the end of the continue . This allows the GDB prompt to return so other commands can be executed. Using the interrupt , execution can be stopped should thread 3 become interesting again. (gdb) interrupt [Thread 0x7ffff75d2710 (LWP 4688)] #3 stopped. 0x000000343f4a6a6d in nanosleep () at ../sysdeps/unix/syscall-template.S:82 82 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) It is also possible to go back to the original main thread and examine it some more. (gdb) thread 1 [Switching to thread 1 (Thread 0x7ffff7fd5720 (LWP 4620))]#0 main () at three-threads.c:34 34 int count1 = 0; (gdb) 36 while(count1 < 1000){ (gdb) 37 printf("Thread 1: %d\n", count1++); (gdb) Thread 1: 0 36 while(count1 < 1000){ (gdb) 37 printf("Thread 1: %d\n", count1++); (gdb) Thread 1: 1 36 while(count1 < 1000){ (gdb) 37 printf("Thread 1: %d\n", count1++); (gdb) Thread 1: 2 36 while(count1 < 1000){ (gdb) print count1 USD3 = 3 (gdb) info threads 3 Thread 0x7ffff75d2710 (LWP 4688) 0x000000343f4a6a6d in nanosleep () at ../sysdeps/unix/syscall-template.S:82 2 Thread 0x7ffff7fd3710 (LWP 4687) thread2 (d=0x0) at three-threads.c:23 * 1 Thread 0x7ffff7fd5720 (LWP 4620) main () at three-threads.c:36 (gdb) As can be seen from the output of info threads, the other threads are where they were left, unaffected by the debugging of thread 1.

Commands:
#include <stdio.h> #include <pthread.h> #include <unistd.h> pthread_t thread; void* thread3 (void* d) { int count3 = 0; while(count3 < 1000){ sleep(10); printf("Thread 3: %d\n", count3++); } return NULL; } void* thread2 (void* d) { int count2 = 0; while(count2 < 1000){ printf("Thread 2: %d\n", count2++); } return NULL; } int main (){ pthread_create (&thread, NULL, thread2, NULL); pthread_create (&thread, NULL, thread3, NULL); //Thread 1 int count1 = 0; while(count1 < 1000){ printf("Thread 1: %d\n", count1++); } pthread_join(thread,NULL); return 0; }
gcc -g three-threads.c -o three-threads -lpthread gdb ./three-threads
(gdb) break thread3 Breakpoint 1 at 0x4006c0: file three-threads.c, line 9. (gdb) break thread2 Breakpoint 2 at 0x40070c: file three-threads.c, line 20. (gdb) break main Breakpoint 3 at 0x40074a: file three-threads.c, line 30.
(gdb) run [...] Breakpoint 3, main () at three-threads.c:30 30 pthread_create (&thread, NULL, thread2, NULL); [...] (gdb) info threads * 1 Thread 0x7ffff7fd5720 (LWP 4620) main () at three-threads.c:30 (gdb)
(gdb) next [New Thread 0x7ffff7fd3710 (LWP 4687)] 31 pthread_create (&thread, NULL, thread3, NULL); (gdb) Breakpoint 2, thread2 (d=0x0) at three-threads.c:20 20 int count2 = 0; next [New Thread 0x7ffff75d2710 (LWP 4688)] 34 int count1 = 0; (gdb) Breakpoint 1, thread3 (d=0x0) at three-threads.c:9 9 int count3 = 0; info threads 3 Thread 0x7ffff75d2710 (LWP 4688) thread3 (d=0x0) at three-threads.c:9 2 Thread 0x7ffff7fd3710 (LWP 4687) thread2 (d=0x0) at three-threads.c:20 * 1 Thread 0x7ffff7fd5720 (LWP 4620) main () at three-threads.c:34
(gdb) thread 2 0 thread2 (d=0x0) at three-threads.c:20 20 int count2 = 0; (gdb) list 15 return NULL; 16 } 17 18 void* thread2 (void* d) 19 { 20 int count2 = 0; 21 22 while(count2 < 1000){ 23 printf("Thread 2: %d\n", count2++); 24 }
(gdb) next 22 while(count2 < 1000){ (gdb) print count2 USD1 = 0 (gdb) next 23 printf("Thread 2: %d\n", count2++); (gdb) next Thread 2: 0 22 while(count2 < 1000){ (gdb) next 23 printf("Thread 2: %d\n", count2++); (gdb) print count2 USD2 = 1 (gdb) info threads 3 Thread 0x7ffff75d2710 (LWP 4688) thread3 (d=0x0) at three-threads.c:9 * 2 Thread 0x7ffff7fd3710 (LWP 4687) thread2 (d=0x0) at three-threads.c:23 1 Thread 0x7ffff7fd5720 (LWP 4620) main () at three-threads.c:34 (gdb)
(gdb) thread 3 0 thread3 (d=0x0) at three-threads.c:9 9 int count3 = 0; (gdb) list 4 5 pthread_t thread; 6 7 void* thread3 (void* d) 8 { 9 int count3 = 0; 10 11 while(count3 < 1000){ 12 sleep(10); 13 printf("Thread 3: %d\n", count3++); (gdb)
(gdb) continue & (gdb) Thread 3: 0 Thread 3: 1 Thread 3: 2 Thread 3: 3
(gdb) interrupt 3 stopped. 0x000000343f4a6a6d in nanosleep () at ../sysdeps/unix/syscall-template.S:82 82 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) thread 1 0 main () at three-threads.c:34 34 int count1 = 0; (gdb) next 36 while(count1 < 1000){ (gdb) next 37 printf("Thread 1: %d\n", count1++); (gdb) next Thread 1: 0 36 while(count1 < 1000){ (gdb) next 37 printf("Thread 1: %d\n", count1++); (gdb) next Thread 1: 1 36 while(count1 < 1000){ (gdb) next 37 printf("Thread 1: %d\n", count1++); (gdb) next Thread 1: 2 36 while(count1 < 1000){ (gdb) print count1 USD3 = 3 (gdb) info threads 3 Thread 0x7ffff75d2710 (LWP 4688) 0x000000343f4a6a6d in nanosleep () at ../sysdeps/unix/syscall-template.S:82 2 Thread 0x7ffff7fd3710 (LWP 4687) thread2 (d=0x0) at three-threads.c:23 * 1 Thread 0x7ffff7fd5720 (LWP 4620) main () at three-threads.c:36 (gdb)