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;.
Solved it, there wasn't much a problem after all. Here are instructions, if anyone has a similar issue:
Compile with gcc -ggdb main.c -o main -lpthread (yes, that's -ggdb and not -g, it appears to make a difference)
Run the debugger with gdb main or, in Emacs, with M-x gdb (and the command gdb -i=mi main)
Hugely important here: Emacs has by default the variable 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!
Continue doing whatever, we have the desired behavior now :)
Related
#include <stdio.h>
#include <sys/wait.h>
#include <pthread.h>
void* runfunc(void* arguments){
printf("in run thread\n");
return NULL;
}
int main(void)
{
pthread_t pthread_id;
pthread_create(&pthread_id, NULL, runfunc, NULL);
printf("after pthread creation\n");
return 0;
}
$ gcc -pthread intro.c
$ ./a.out
after pthread creation
in run thread
in run thread
$ ./a.out
after pthread creation
$
There are 4 types of outputs for this program on linux.
"after pthread creation" -> this output can be easily understood as before thread execution process completes and exits and deletes all threads.
"after pthread creation
in " -> this output can also be understood as while process was exiting thread executed a little bit to print in
"in running thread
after pthread creation" -> this output can also be easily understood
"after pthread creation
in running thread
in running thread" -> now i don't get why am i getting "in running thread" 2 times instead of once.
Linux implementation of threads is considered.
This is my program code:
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
void function() {
srand(time(NULL));
while(1) {
int n = rand();
printf("%d ", n);
//sleep(1);
}
}
int main() {
pid_t pid;
pid = fork();
if (pid == 0) {
function();
}
}
With the sleep line commented out (as in the code above) the program works fine (i.e. it prints a bunch of random numbers too fast to even see if they are actually random), but if I remove the comment the program doesn't print anything and exits (not even the first time, before it gets to the sleep), even though it compiles without warnings or errors with or without the comment.
but if I remove the comment the program doesn't print anything and exits
It does not print, but it does not really exit either. It will still be running a process in the background. And that process runs your infinite while loop.
Using your code in p.c:
$ gcc p.c
$ ./a.out
$ ps -A | grep a.out
267282 pts/0 00:00:00 a.out
$ killall a.out
$ killall a.out
a.out: no process found
The problem is that printf does not really print. It only sends data to the output buffer. In order to force the output buffer to be printed, invoke fflush(stdout)
If you're not flushing, then you just rely on the behavior of the terminal you're using. It's very common for terminals to flush when you write a newline character to the output stream. That's one reason why it's preferable to use printf("data\n") instead of printf("\ndata"). See this question for more info: https://softwareengineering.stackexchange.com/q/381711/283695
I'd suspect that if you just leave your program running, it will eventually print. It makes sense that it has a finite buffer and that it flushes when it gets full. But that's just an (educated) guess, and it depends on your terminal.
it prints a bunch of random numbers too fast to even see if they are actually random
How do you see if a sequence of numbers is random? (Playing the devils advocate)
I believe you need to call fflush(3) from time to time. See also setvbuf(3) and stdio(3) and sysconf(3).
I guess that if you coded:
while(1) {
int n = rand();
printf("%d ", n);
if (n % 4 == 0)
fflush(NULL);
sleep(1);
}
The behavior of your program might be more user friendly. The buffer of stdout might have several dozens of kilobytes at least.
BTW, I could be wrong. Check by reading a recent C draft standard (perhaps n2176).
At the very least, see this C reference website then syscalls(2), fork(2) and sleep(3).
You need to call waitpid(2) or a similar function for every successful fork(2).
If on Linux, read also Advanced Linux Programming and use both strace(1) and gdb(1) to understand the behavior of your program. With GCC don't forget to compile it as gcc -Wall -Wextra -g to get all warnings and debug info.
Consider also using the Clang static analyzer.
Here is my code:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
pthread_t ntid;void
printids(const char *s) {
printf("%s \n", s);
}
void *
thr_fn(void *arg) {
printids("new thread: ");
return((void *)0);
}
int
main(void) {
pthread_create(&ntid, NULL, thr_fn, NULL);
printids("main thread:");
}
I'm running it on Red Hat Enterprise Linux Workstation release 6.5 .
Here is my compiling command
gcc -ansi -g -std=c99 -Wall -DLINUX -D_GNU_SOURCE threadid.c -o threadid -pthread -lrt -lbsd
Here is the output:
main thread:
new thread:
new thread:
Why "new thread" has been printed twice?
I doubt this may related to buffering mechanism in Linux. But after I added fflush(stdout) and fsync(1) in the end of each function. The output is almost the same.
If you run the program several times. The output differs:
main thread:
new thread:
or
main thread:
new thread:
new thread:
Or
main thread:
Most libc libraries do buffer the output as you mentioned. And at the end of the program (when the main thread exits), they flush all the buffers and exit.
There is a slight possibility that your new thread has flushed the output but before it could update the state of the buffer, the main program exited and the cleanup code flushed the same buffer again. Since these buffers are local to the thread I am sure they won't have concurrency mechanism. But because of this rare case it might get messed up.
You can try
err = pthread_create(&ntid, NULL, thr_fn, NULL);
printids("main thread:");
pthread_join(ntid, NULL);
At the end of the main function and check if the problem is solved.
This will cause your main function to wait till the new thread is finished (including the flushing operation it does).
Double output is possible on glibc-based linux systems due to a nasty bug in glibc: if the FILE lock is already held at the time exit tries to flush, the lock is simply ignored and the buffer access is performed with no synchronization. This would be a great test case to report to glibc to pressure them to fix it, if you can reproduce it reliably.
I am trying to debug code written for Raspberry Pi on my Ubuntu laptop. I am using:
the Raspberry Pi Toolchain and (partial ?) root fs obtained with git clone git://github.com/raspberrypi/tools.git executed in ~/rpi
qemu virtualizer installed from Ubuntu repositiories - qemu-arm reports
version 2.0.0
the following test case:
#include <pthread.h>
#include <stdio.h>
static void *thread(void *arg)
{
static char szReturn[] = "Me too";
puts((char *)arg);
puts("Hello, I'm Thread");
return szReturn;
}
int main(int argc, char *argv[])
{
pthread_t tid;
char szGreeting[] = "Hello, I'm Main", *reply;
if (pthread_create(&tid, NULL, &thread, szGreeting) != 0)
{
perror("pthread_create says: ");
return 1;
}
puts("Nice to meet you");
if (pthread_join(tid, (void **)&reply) == 0)
puts(reply);
return 0;
}
After adding ~/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin to the PATH (I am using 64 bit Ubuntu), I do (from the directory in which the test code resides):
arm-linux-gnueabihf-gcc -g -O0 test.c -o test -lpthread
qemu-arm -L ~/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/arm-linux-gnueabihf/libc ./test
I get the expected output, so the thread creation and execution works.
However, if I do:
qemu-arm -g 1234 -L ~/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/arm-linux-gnueabihf/libc ./test in one terminal, to launch qemu and have it waiting for the debugger to connect to it
arm-linux-gnueabihf-gdb -ex="target remote localhost:1234" -x="set breakpoint pending on" -ex="break main" ./test in another terminal, to start debugging the program with gdb
I get in gdb, after 'continue' I reach main, I set breakpoints to thread, 21 and 24, I next OK to the ptread_create call, so debugging the main thread works, but:
when it executes pthread_create, instead of hitting one of the 3 breakpoints (the thread, the create failure or the create success cases), gdb reports "inferior terminated' and the session ends
back in the qemu terminal though, the program has generated the normal output, so the thread was created and executed, and the whole program worked as expected
So gdb can not debug multithreaded programs in this configuration/setup?! What am I missing?
Could the fact that I am running Ubuntu in a Parallels virtual machine on an OSX machine have something to do with it? I don't have a dedicated Ubuntu machine to test, but I doubt it.
Update: On a native Fedora system the behavior is even worse: the breakpoints are also not taken, but it also crashes in puts and pthread_join.
Thanks in advance
I have a C linux application (A) that spawns another process (P) when it is started. When I want to debug P I start A as usual and I connect with ddd/gdb to P.
Problems appear when I want to debug the entry-point (start of main) of P. If I follow the usual approach when I connect the debugger to P is already to late. The solution I've found was to insert a sleep at the begining of the main of P so I have time to connect with gdb but this is not a very elegant solution.
I've also tried using asm("int $3") but it doesn't seems to work.
Do you have any idea how I could solve this problem? (preferably without altering the code of A or P)
You should use this option:
set follow-fork-mode mode
Where mode is one of parent, child or ask.
To follow the parent (this is the default) use:
set follow-fork-mode parent
To follow the child:
set follow-fork-mode child
To have the debugger ask you each time:
set follow-fork-mode ask
So basically you'd start out connecting gdb to A, then set gdb to follow the child, and then when A spawns P, gdb will connect to P and detach from A.
In addition to the Nathan Fellman's answer, catchpoints come in handy, i.g.:
catch exec
Catchpoint works as a breakpoint. Every time a call to exec() syscall is detected, GDB stops. This allows you to set any breakpoint (i.g. break main) in any newly loaded executable before continuing. Another catchpoint catch fork works similarly for fork() syscall detection.
It is especially convenient:
when both parent and child has to be followed (set detach-on-fork off);
when parent processes forks often loading various executables.
exec part with file + break main
The fork was part was explained at: https://stackoverflow.com/a/377295/895245
Now for the exec:
a.c:
#include <unistd.h>
int main(void) {
execl("./b", "./b", "ab", "cd", (char*)NULL);
return 1;
}
b.c:
#include <stdio.h>
int main(int argc, char **argv ) {
printf("%s\n", argv[0]);
printf("%s\n", argv[1]);
}
Then:
gcc -g a.c -o a
gcc -g b.c -o b
gdb -nh -q a
Now on the interactive session:
Reading symbols from a...done.
(gdb) start
Temporary breakpoint 1 at 0x4004ea: file a.c, line 4.
Starting program: /home/ciro/test/gdb-exec/a
Temporary breakpoint 1, main () at a.c:4
4 execl("./b", "./b", "ab", "cd", (char*)NULL);
(gdb) file b
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Load new symbol table from "b"? (y or n) y
Reading symbols from b...done.
(gdb) b main
Breakpoint 2 at 0x4004f5: file b.c, line 4.
(gdb) n
Breakpoint 2, main (argc=0, argv=0x7fffffffa570) at b.c:4
4 printf("%s\n", argv[1]);
(gdb) n
process 4877 is executing new program: /home/ciro/test/gdb-exec/b
Breakpoint 2, main (argc=3, argv=0x7fffffffa598) at b.c:4
4 printf("%s\n", argv[1]);
(gdb) n
ab
5 printf("%s\n", argv[2]);
(gdb) n
cd
6 }
(gdb)
You just have to make sure that you go up to the exec before running file, possibly with a b execl, since after that you will be using symbols from the new file.
Tested in Ubuntu 14.04, gdb 7.7.1.
You should be able to do this by making use of gdb's remote debugging features, specifically gdbserver. In effect, launch (P) using gdbserver. These links have more detailed info:
Using gdbserver
GDB Remote Debugging
set a break point at main(), it will also break at main() of the execed program.