• Nginx代码调试——gdb工具


    参考网上的资料,写了一个configprint模块,其功能为打印输出location配置内容,并计数访问次数。

    代码链接如下:https://github.com/PaulWeiHan/nginx_module_development

    程序的编写到运行总不是一帆风顺的,编译通过,运行不过的情况是最让我抓狂的。

    这里记录一下gdb调试过程。供大家参考:

    (这里没有gdb命令说明,请自行百度)

    我使用的是nginx的默认模式即:

    daemon on;
    master_process on;
    worker_processes  1;

    我们知道。nginx默认执行的时候,是以daemon模式运行在后台,并且,由master进程fork出多个work子进程来监听端口的。切到nginx目录,执行下面命令:

    1 gdb
    2 shell sbin/nginx
    3 shell pidof nginx

    这样,我们就可以得到nginx的pid,一般会是两个,由于worker子进程是fork master得来的,所以自然worker进程的pid较大。利用gdb的attach和detach命令追踪worker子进程。

    (gdb) shell pidof nginx
    11903 11902
    (gdb) attach 11903
    Attaching to process 11903
    Reading symbols from /home/renwh/nginx/sbin/nginx...done.
    Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done.
    [Thread debugging using libthread_db enabled]
    Loaded symbols for /lib64/libpthread.so.0
    Reading symbols from /lib64/libcrypt.so.1...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libcrypt.so.1
    Reading symbols from /lib64/libpcre.so.0...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libpcre.so.0
    Reading symbols from /lib64/libz.so.1...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libz.so.1
    Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libc.so.6
    Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
    Loaded symbols for /lib64/ld-linux-x86-64.so.2
    Reading symbols from /lib64/libfreebl3.so...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libfreebl3.so
    Reading symbols from /lib64/libdl.so.2...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libdl.so.2
    Reading symbols from /lib64/libnss_files.so.2...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libnss_files.so.2
    0x00000031684e8fb3 in __epoll_wait_nocancel () from /lib64/libc.so.6
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6.x86_64 nss-softokn-freebl-3.14.3-17.el6.x86_64 pcre-7.8-6.el6.x86_64 zlib-1.2.3-29.el6.x86_64
    (gdb) 

    子进程即worker进程在运行后会停留在epoll_wait处等待相应的事件发生,而这个函数调用被封装在ngx_process_events_and_timers 中。于是我们在这个函数出设置一个断点:b ngx_process_events_and_timers.然后采用命令c,使得nginx一直运行,直到遇到第一个断点:

    1 (gdb) b ngx_process_events_and_timers
    2 Breakpoint 1 at 0x41b565: file src/event/ngx_event.c, line 195.
    3 (gdb) c
    4 Continuing.
    5 
    6 Breakpoint 1, ngx_process_events_and_timers (cycle=0x9be050) at src/event/ngx_event.c:195
    7 195     {
    8 (gdb) 

    进去之后,一直用n向下运行,直到找到ngx_process_events,然后用s追踪进该函数,一直n,直到运行到epoll_wait,发现,停在了这里,我们知道work子进程在等待事件了。

    Breakpoint 1, ngx_process_events_and_timers (cycle=0x9be050) at src/event/ngx_event.c:195
    195     {
    (gdb) n
    199         if (ngx_timer_resolution) {
    (gdb) n
    204             timer = ngx_event_find_timer();
    (gdb) n
    218         if (ngx_use_accept_mutex) {
    (gdb) n
    240         delta = ngx_current_msec;
    (gdb) n
    242         (void) ngx_process_events(cycle, timer, flags);
    (gdb) s
    ngx_epoll_process_events (cycle=0x9be050, timer=18446744073709551615, flags=1)
        at src/event/modules/ngx_epoll_module.c:702
    702     {
    (gdb) n
    717         events = epoll_wait(ep, event_list, (int) nevents, timer);
    (gdb) n

    这时候,你只需要打开一个浏览器,访问你配置好的nginx模块的url,然后你就会发现gdb可以向下运行了。这时候,你需要在你自己的handler函数处设置断点,然后c,你会发现,又一次调用了ngx_process_events_and_timers函数,s进入函数,继续c运行,然后gdb会停在你自己的handler函数入口,这里是:ngx_http_configprint_handler。s追踪进去,你就可以单步执行你自己写的handler函数,进行debug了。

     1 (gdb) b ngx_http_configprint_handler
     2 Breakpoint 2 at 0x4699a7: file /home/renwh/src/nginx-1.9.2/configprint//ngx_http_configprint_module.c, line 184.
     3 (gdb) c
     4 Continuing.
     5 
     6 Breakpoint 1, ngx_process_events_and_timers (cycle=0x9be050) at src/event/ngx_event.c:195
     7 195     {
     8 (gdb) s
     9 199         if (ngx_timer_resolution) {
    10 (gdb) n
    11 204             timer = ngx_event_find_timer();
    12 (gdb) n
    13 218         if (ngx_use_accept_mutex) {
    14 (gdb) n
    15 240         delta = ngx_current_msec;
    16 (gdb) c
    17 Continuing.
    18 
    19 Breakpoint 2, ngx_http_configprint_handler (r=0x9c8550)
    20     at /home/renwh/src/nginx-1.9.2/configprint//ngx_http_configprint_module.c:184
    21 184     {
    22 (gdb) n
    23 189             u_char ngx_my_string[1024] = {0};
    24 (gdb) n
    25 193             ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "ngx_http_configprint_handler is

    gdb不光可以帮你debug,还可以帮你理解整个nginx的运行过程。你可以尝试在自己的handler挂载函数,loc_conf创建函数等地方添加断点,来查看整个模块的调用过程。

    个人理解,欢迎讨论。联系方式:rwhsysu@163.com

  • 相关阅读:
    re.sub函数的深入了解
    xpath
    改变评分查询
    Boolean Query
    固定分数查询
    Unicode编码的原型
    java中基本类型占用字节数
    Java Socket网络编程的经典例子(转)
    (转)工厂模式
    (转)java垃圾回收机制
  • 原文地址:https://www.cnblogs.com/paulweihan/p/4667216.html
Copyright © 2020-2023  润新知