Debug with Gdb[i]Nginx[ii] and the use of GDB debugging other programs are no different, just nginx can be daemon program, can also be executed in multiple processes, so the use of GDB debugging and ordinary will be slightly different.
Of course, we can choose to set Nginx to non-daemon mode and execute it as a single process. And this needs to be done such as the following settings:
Daemon off;
Master_process off;
This is the first case:
This setting of Nginx under GdB debugging is very common, the process can be [III] is this:
To run the command:
[Email protected]:/usr/local/nginx/sbin$ sudo gdb./nginx
The current folder is in/usr/local/nginx/sbin, which has a running program Nginx under the folder. The last command is to use GDB to start debugging Nginx, enter the GDB command line, directly input R can run Nginx:
(GDB) R
Starting program:/usr/local/nginx/sbin/nginx
SRC/CORE/NGX_CONF_FILE.C 1163:1 million
===============================
Ngx_timer_resolution 1000000
Since Nginx was executed in the form. The keyboard input is taken over by Nginx, the GDB command cannot be entered at this time, so you need to press CTRL + C to fall back to the GDB command line mode, and Nginx is interrupted in the __kernel_vsyscall call, the input BT command can view the call stack information:
(GDB) R
Starting program:/usr/local/nginx/sbin/nginx
SRC/CORE/NGX_CONF_FILE.C 1163:1 million
===============================
Ngx_timer_resolution 1000000
^c
Program received signal SIGINT, Interrupt.
0xb7f29430 in __kernel_vsyscall ()
(GDB) bt
#0 0xb7f29430 in __kernel_vsyscall ()
#1 0xb7e081a8 in epoll_wait () from/lib/tls/i686/cmov/libc.so.6
#2 0x08073ea3 in Ngx_epoll_process_events (Cycle=0x860ad60, timer=4294967295,
flags=0) at src/event/modules/ngx_epoll_module.c:405
#3 0x080668ee in Ngx_process_events_and_timers (CYCLE=0X860AD60)
At src/event/ngx_event.c:253
#4 0x08071618 in Ngx_single_process_cycle (CYCLE=0X860AD60)
At src/os/unix/ngx_process_cycle.c:283
#5 0x0804a926 in Main (Argc=1, argv=0xbfd2ae44) at src/core/nginx.c:372
(GDB)
OK, let's set a breakpoint for Nginx. This is very easy, for example, to set a breakpoint on the function ngx_process_events_and_timers, and then enter the command C to continue to run Nginx:
#4 0x08071618 in Ngx_single_process_cycle (CYCLE=0X860AD60)
At src/os/unix/ngx_process_cycle.c:283
#5 0x0804a926 in Main (Argc=1, argv=0xbfd2ae44) at src/core/nginx.c:372
(GDB) B ngx_process_events_and_timers
Breakpoint 1 at 0x80667d6:file src/event/ngx_event.c, line 200.
(GDB) C
Continuing.
Breakpoint 1, ngx_process_events_and_timers (CYCLE=0X860AD60)
At src/event/ngx_event.c:200
200 {
(GDB)
As a result, gdb here immediately prompts for a breakpoint interrupt, which is precisely tuned to this function. Maybe you won't be interrupted immediately. So GDB has been parked behind the continuing. At this point we have to take the initiative to trigger the event (or wait, the time may be very long, depending on your nginx settings) to make Nginx call this function. For example, using the browser to visit the Nginx monitoring site, so that nginx events occur.
After the breakpoint breaks, we debug and trace with the S, C and other GDB general commands. These do not need to say more:
200 {
(GDB) s
__cyg_profile_func_enter (this=0x80667d0, call=0x8071618)
At src/core/my_debug.c:65
Warning:source file is more recent than executable.
My_debug_print ("enter\n%p\n%p\n", call, this);
(GDB)
66}
(GDB) C
Continuing.
Ngx_timer_resolution 1000000
Another situation:
When you execute Nginx in daemon mode (that is, configuration option: daemon on;), the method above is not effective. The reason is very easy, when nginx in daemon mode execution, this boot process nginx will fork several times. And those parent processes are already out of the way, so what you see is this:
[Email protected]:/usr/local/nginx/sbin$ sudo gdb./nginx
GNU gdb 6.8-debian
Copyright (C) Free Software Foundation, Inc.
License gplv3+: GNU GPL version 3 or later This was free software:you was free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "Show copying"
and "Show warranty" for details.
This GDB is configured as "I486-linux-gnu" ...
(GDB) R
Starting program:/usr/local/nginx/sbin/nginx
SRC/CORE/NGX_CONF_FILE.C 1163:1 million
===============================
Program exited normally.
(GDB)
In fact, Nginx did not quit, the exit is the parent (or grandfather) process, and GDB did not follow the fork to follow:
[Email protected]:/usr/local/nginx/sbin$ pidof Nginx
7908
GDB considers such a situation and therefore provides the corresponding Follow-fork-mode option:
It is used in the following ways:
Set Follow-fork-mode [Parent|child]
Description
After parent:fork, continue debugging the parent process. Child processes are not affected.
Child:fork after the child process is debugged. The parent process is not affected.
When this option is set, the other mode operation is the same as the one described earlier, with the relevant scale as follows:
[Email protected]:/usr/local/nginx/sbin$ sudo gdb./nginx-q
(GDB) R
Starting program:/usr/local/nginx/sbin/nginx
SRC/CORE/NGX_CONF_FILE.C 1163:1 million
===============================
Program exited normally.
(gdb) Shell pidof Nginx
9723
(gdb) Shell kill-9 9723
(GDB) Set Follow-fork-mode child
(GDB) B ngx_process_events_and_timers
Breakpoint 1 at 0x80667d6:file src/event/ngx_event.c, line 200.
(GDB) R
Starting program:/usr/local/nginx/sbin/nginx
SRC/CORE/NGX_CONF_FILE.C 1163:1 million
===============================
[Switching to process 9739]
Breakpoint 1, ngx_process_events_and_timers (CYCLE=0X8FF0D60)
At src/event/ngx_event.c:200
200 {
(GDB) s
[Tcsetpgrp failed in terminal_inferior:no such process]
__cyg_profile_func_enter (this=0x80667d0, call=0x8071618)
At src/core/my_debug.c:65
Warning:source file is more recent than executable.
My_debug_print ("enter\n%p\n%p\n", call, this);
(GDB) C
Continuing.
Above we set breakpoints first, so that after executing the R command, Nginx will voluntarily be interrupted to return to the GDB command line. Assuming that you do not, you will not be able to return to the GDB command line. That is, press CTRL + C no effect, because Nginx is executed in daemon mode, the input and output has been redirected, Nginx did not receive this CTRL + C input.
Of course, there is no other way. For example, another shell form. Use the KILL command to send an SIGINT signal to the NGINX process, which is the same as pressing CTRL + C, such as the following (assuming 9897 is the Nginx process ID number):
[Email protected]:~$ sudo kill-2 9897
Another situation:
The third case is that no matter the Nginx execution mode, it is generic, that is, using GdB's Attach, Detach command.
This assumes the relevant configuration of the current Nginx:
daemon on;
Master_process on;
Worker_processes 1;
That is daemon mode. Multi-Process Execution nginx.
[Email protected]:/usr/local/nginx/sbin$ sudo gdb-q
(GDB) shell./nginx
SRC/CORE/NGX_CONF_FILE.C 1163:1 million
===============================
(gdb) Shell pidof Nginx
10246 10245
(GDB)
Can see a common two nginx process, here 10245 is the master process. And 10246 is the worker process.
We want to debug worker 10246 such as the following:
(gdb) Attach 10246
Attaching to Program:/usr/local/nginx/sbin/nginx, Process 10246
Reading symbols From/lib/tls/i686/cmov/libcrypt.so.1...done.
Loaded symbols For/lib/tls/i686/cmov/libcrypt.so.1
Reading symbols From/lib/libpcre.so.3...done.
Loaded symbols for/lib/libpcre.so.3
Reading symbols From/usr/lib/libz.so.1...done.
Loaded symbols For/usr/lib/libz.so.1
Reading symbols From/lib/tls/i686/cmov/libc.so.6...done.
Loaded symbols for/lib/tls/i686/cmov/libc.so.6
Reading symbols From/lib/ld-linux.so.2...done.
Loaded symbols for/lib/ld-linux.so.2
Reading symbols From/lib/tls/i686/cmov/libnss_compat.so.2...done.
Loaded symbols for/lib/tls/i686/cmov/libnss_compat.so.2
Reading symbols From/lib/tls/i686/cmov/libnsl.so.1...done.
Loaded symbols For/lib/tls/i686/cmov/libnsl.so.1
Reading symbols From/lib/tls/i686/cmov/libnss_nis.so.2...done.
Loaded symbols for/lib/tls/i686/cmov/libnss_nis.so.2
Reading symbols From/lib/tls/i686/cmov/libnss_files.so.2...done.
Loaded symbols for/lib/tls/i686/cmov/libnss_files.so.2
0xb8016430 in __kernel_vsyscall ()
(GDB) B ngx_process_events_and_timers
Breakpoint 3 at 0x80667d6:file src/event/ngx_event.c, line 200.
(GDB) C
Continuing.
Breakpoint 3, Ngx_process_events_and_timers (cycle=0x8f43d68) at src/event/ngx_event.c:200
200 {
(GDB) Detach
Detaching from Program:/usr/local/nginx/sbin/nginx, Process 10246
(GDB)
Overall, the third method is the best.
[i] http://www.gnu.org/software/gdb/[ii] Nginx was compiled with the-G option turned on. [III] means that the following methods are just one of many methods.
Nginx Source Code Analysis--GDB debugging