Reputation: 2034
I have the following code (source):
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid) {
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld\n", tid);
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
int rc;
long t;
for (t=0; t<NUM_THREADS; t++) {
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
// wait for all threads to die
pthread_exit(NULL);
}
I compile with gcc -g main.c -o main -lpthread
. I am using GDB for debugging. What I want is to place a breakpoint at the second line of PrintHello, i.e. at tid = (long)threadid
, and have the execution stop there (whatever the thread) and let me do stuff like look at the value of variable threadid
.
I want to achieve this in Emacs' GDB implementation - which we may assume for the purposes of this question as simply GDB (don't worry that it's run inside Emacs). So far I can place the breakpoint at the desired line, and sometimes the little arrow showing the current line where the program is at does indeed stop at this line:
However when I type into the GDB prompt print threadid
I get back No symbol "threadid" in current context.
and the arrow jumps immediately to some breakpoint that I set in main():
My guess is that this occurs because the "pausing" of program execution happens for the main thread, which is not the thread running PrintHello
. PrintHello
is run by thread t
- since this is not the thread paused by GDB, it prints the hello world message and exists immediately. By the time I get around to typing print threadid
, this thread is already dead and the program is back in main()... hence the effect.
I tried to resolve this by typing something like break <LineNumber> thread <ThreadID>
but this is no good since in this program the created threads last for a split second. So I am never actually at a point where info thread
shows anything except the main thread. It's simply not humanly possible to "catch" the program at a point where there is the main thread and a newly created thread running PrintHello
- since this situation lasts for I guess a few microseconds.
Please help me to achieve this simple debug objective of halting execution of whatever thread is executing PrintHello
at the line tid = (long)threadid;
.
Upvotes: 2
Views: 590
Reputation: 2034
Solved it, there wasn't much a problem after all. Here are instructions, if anyone has a similar issue:
gcc -ggdb main.c -o main -lpthread
(yes, that's -ggdb
and not -g
, it appears to make a difference)gdb main
or, in Emacs, with M-x gdb
(and the command gdb -i=mi main
)
gdb-non-stop-setting
set to t
, which means it tries to run GDB in non-stop mode. According to docs, this is NOT what I want - I want all-stop mode. Thus, either do a set-variable
or put (setq gdb-non-stop-setting nil)
in your init file (e.g. ~/.emacs.d/init.el
). Only once this is done should you launch M-x gdb
from inside Emacs...(gdb) b 9
to set the breakpoint to line 9(gdb) r
to run the program. Execution will stop when one of the threads reaches line 9, i.e. tid = (long)threadid;
. All other threads will also stop! Perfect!(gdb) c
to continue. Execution will stop when another thread reaches line 9. Great!Upvotes: 1