(gdb) c

Continuing.

[New Thread 356]

[Switching to Thread 356]

Breakpoint 1, main (argc=0x1, argv=0xbe807dd4) at forker.c:104

104       time(&start_time);

(gdb) b worker_process

Breakpoint 2 at 0x8784: file forker.c, line 45.

(gdb) c

Continuing.

Detaching after fork from child process 357.

Detaching after fork from child process 358.

Detaching after fork from child process 359.

Detaching after fork from child process 360.

Detaching after fork from child process 361.

Detaching after fork from child process 362.

Detaching after fork from child process 363.

Detaching after fork from child process 364.

Notice that eight child processes were spawned, with PID values from 357 to 364. The parent process was instantiated with PID 356. When the breakpoint in main() was hit, we entered a breakpoint at the worker_process () routine, which each child process executes upon fork(). Letting the program continue from main, we see each of the new processes spawned and detached by the debugger. They never hit the breakpoint because GDB is attached to the main process, which never executes the worker_process() routine.

If you need to debug each process, you must execute a separate independent GDB session and attach to the child process after it is forked(). The GDB documentation referenced at the end of this chapter outlines a useful technique to place a call to sleep() in the child process, giving you time to attach a debugger to the new process. Attaching to a new process is explained in Section 15.5.2, 'Attaching to a Running Process.'

If you simply need to follow the child process, set the follow-fork-mode to follow child before your parent reaches the fork() system call. Listing 15-13 shows this.

Listing 15-13. GDB in follow-fork-mode = child

(gdb) target remote 192.168.1.141:2001

0x40000790 in ?? ()

(gdb) set follow-fork-mode child

(gdb) b worker_process

Breakpoint 1 at 0x8784: file forker.c, line 45.

(gdb) c

Continuing.

[New Thread 401]

Attaching after fork to child process 402.

[New Thread 402]

[Switching to Thread 402]

Breakpoint 1, worker_process () at forker.c:45

45         int my_pid = getpid();

(gdb) c

Continuing.

Here we see the parent process being instantiated as PID 401. When the first child is spawned by the fork () system call, GDB detaches silently from the parent thread of execution and attaches to the newly spawned child process having PID 402. GDB is now in control of the first child process and honors the breakpoint set at worker_process(). Notice, however, that the other child processes spawned by the code snippet from Listing 15-11 are not debugged and continue to run to their own completion.

In summary, using GDB in this fashion, you are limited to debugging a single process at a time. You can debug through the fork() system call, but you have to decide which thread of execution to follow through the fork() call, either the parent or the child. As mentioned in the introduction to this section, you can use multiple independent GDB sessions if you must debug more than one cooperating process at a time.

15.4.2. Debugging Multithreaded Applications

If your application uses the POSIX thread library for its threading functions, GDB has additional capabilities to handle concurrent debugging of a multithreaded application. The Native Posix Thread Library (NPTL) has become the de facto standard thread library in use on Linux systems, including embedded Linux systems. The rest of this discussion assumes that you are using this thread library.

For this section, we use a demonstration program that spawns a number of threads using the pthread_create() library function in a simple loop. After the threads are spawned, the main() routine simply waits for keyboard input to terminate the application. Each thread displays a short message on the screen and sleeps for a predetermined time. Listing 15-14 shows the startup sequence on the target board.

Listing 15-14. Target Threads Demo Startup

root@coyote:/workspace # gdbserver localhost:2001 ./tdemo

Process ./tdemo created; pid = 671

Listening on port 2001

Remote debugging from host 192.168.1.10

   ^^^^^ Previous three lines displayed by gdbserver

tdemo main() entered: My pid is 671

Starting worker thread 0

Starting worker thread 1

Starting worker thread 2

Starting worker thread 3

As in our previous examples, gdbserver prepares the application for running and waits for a connection from our host-based cross-gdb. When GDB connects, gdbserver reports the connection with the Remote debugging... message. Now we start GDB on the host and connect. Listing 15-15 reproduces this half of the session.

Listing 15-15. Host GDB Connecting to Target Threads Demo

$ xscale_be-gdb -q tdemo

(gdb) target remote 192.168.1.141:2001

0x40000790 in ?? ()

(gdb) b tdemo.c:97

Breakpoint 1 at 0x88ec: file tdemo.c, line 97.

(gdb) c

Continuing.

[New Thread 1059]

[New Thread 1060]

[New Thread 1061]

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату