Show Table of Contents
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) 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
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) next
22 while(count2 < 1000){
(gdb) print count2
$1 = 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
$2 = 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) 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
$3 = 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.

Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.