• 07 nginx 的 worker process 的调试


    前言

     

    呵呵 之前 ngx 的调试, 都是基于 gdb, 这个 能够全局看到的上下文太繁琐了 

    因此 之前思考 如何使用 clion/其他IDE 调试 worker process 

    呵呵 有一些思考的地方, 有一些 尝试的地方, 有一些 失败的地方, 有一些 成功的地方 

    此处梳理一下, 主要的目的是 调试 worker process 子进程

    还有一个 tricks 是, 调试的时候最好修改 优化级别为 O0, 否则 会有一部分变量被优化到寄存器, 导致 gdb/其他调试器 的时候查看不到对应的数据 

    以下截图, 调试基于 nginx-1.18.0

    基于 gdb 的调试

    1. master:nginx-1.18.0 jerry$ ps -ef | grep nginx
    2. 501 2097 1 0 9:34PM ?? 0:00.01 nginx: worker process
    3. 501 2182 2097 0 9:37PM ?? 0:00.00 nginx: master process /Users/jerry/ClionProjects/nginx-1.18.0/objs/nginx -c /usr/local/nginx/conf/nginx.conf -g daemon off;
    4. 501 2196 790 0 9:37PM ttys001 0:00.00 grep nginx
    5. master:nginx-1.18.0 jerry$ sudo gdb attach 2097
    6. // 省略掉一部分 gdb 的输出
    7. 0x00007fff7beaa78a in ?? () from /usr/lib/system/libsystem_kernel.dylib
    8. (gdb) b ngx_http_static_module.c:77
    9. Breakpoint 1 at 0x10183d7ad: file src/http/modules/ngx_http_static_module.c, line 77.
    10. (gdb) c
    11. Continuing.
    12. Breakpoint 1, ngx_http_static_handler (r=0x7ff649000450)
    13. at src/http/modules/ngx_http_static_module.c:77
    14. 77 last = ngx_http_map_uri_to_path(r, &path, &root, 0);
    15. (gdb) print r->uri
    16. $1 = {len = 11, data = 0x7ff649001173 "/index.html"}
    17. (gdb) next
    18. 78 if (last == NULL) {
    19. (gdb) print path
    20. $2 = {len = 33, data = 0x7ff64900117f "/usr/local/nginx/html/index.html"}
    21. (gdb)

    set follow-fork-mode child

    这个期望是从 clion 等 ide 来调试 worker process 

    但是实际在 使用的过程中失败了 

    1. [Thread debugging using libthread_db enabled]
    2. Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    3. Breakpoint 1, ngx_start_worker_processes (cycle=0x1f757d0, n=1, type=-3) at src/os/unix/ngx_process_cycle.c:359
    4. 359 ngx_spawn_process(cycle, ngx_worker_process_cycle,
    5. (gdb) set follow-fork-mode child
    6. (gdb) show follow-fork-mode
    7. Debugger response to a program call of fork or vfork is "child".
    8. [Attaching after Thread 0x7f3055667700 (LWP 10253) fork to child process 10260]
    9. [New inferior 2 (process 10260)]
    10. [Detaching after fork from parent process 10253]
    11. [Inferior 1 (process 10253) detached]
    12. [Thread debugging using libthread_db enabled]
    13. Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

    交换 worker process 和 master process 的业务

    在原有的体系中 master process 是父进程, 然后 worker process 是子进程 

    然后 fork 了之后, debugger 继续 attach 的是父进程 

    那么 方式就是 将 worker process 更新为主进程, master process 更新为子进程, 那么 debugger 调试的不就是 woker process 了? 

    调整方式如下 更新 ngx_process.c:188 位于 ngx_process.ngx_spawn_process 函数中更新如下代码, ”case 0“ 对应于子进程的处理, 更新为父进程的处理, "default" 为父进程的处理, 更新为子进程的处理, 然后 重新编译 调试即可 

    1. switch (pid) {
    2. case -1:
    3. ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
    4. "fork() failed while spawning \"%s\"", name);
    5. ngx_close_channel(ngx_processes[s].channel, cycle->log);
    6. return NGX_INVALID_PID;
    7. case 0:
    8. // ngx_parent = ngx_pid;
    9. // ngx_pid = ngx_getpid();
    10. // proc(cycle, data);
    11. break;
    12. default:
    13. ngx_parent = ngx_pid;
    14. ngx_pid = ngx_getpid();
    15. proc(cycle, data);
    16. break;
    17. }

    运行时调试的情况如下图 

    呵呵 以上不过是介绍了一些 tricks 而已 

  • 相关阅读:
    python作图
    【定语从句练习题】定语从句中的介词
    odoo14 生成PDF报表详解
    史上最全Java面试题,Java面试必备
    别在傻傻的封装对象返回了,来看看这篇SpringBoot返回结果统一包装
    C#的基于.net framework的Winform编程 - 编程手把手系列文章
    分布式事务-Seata-详细图文讲解
    计算机毕业设计Javaweb高校车辆调度系统设计与实现(源码+系统+mysql数据库+lw文档)
    使用JavaStream将List转为Map
    Glide原理
  • 原文地址:https://blog.csdn.net/u011039332/article/details/125699137