呵呵 之前 ngx 的调试, 都是基于 gdb, 这个 能够全局看到的上下文太繁琐了
因此 之前思考 如何使用 clion/其他IDE 调试 worker process
呵呵 有一些思考的地方, 有一些 尝试的地方, 有一些 失败的地方, 有一些 成功的地方
此处梳理一下, 主要的目的是 调试 worker process 子进程
还有一个 tricks 是, 调试的时候最好修改 优化级别为 O0, 否则 会有一部分变量被优化到寄存器, 导致 gdb/其他调试器 的时候查看不到对应的数据
以下截图, 调试基于 nginx-1.18.0
- master:nginx-1.18.0 jerry$ ps -ef | grep nginx
- 501 2097 1 0 9:34PM ?? 0:00.01 nginx: worker process
- 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;
- 501 2196 790 0 9:37PM ttys001 0:00.00 grep nginx
- master:nginx-1.18.0 jerry$ sudo gdb attach 2097
- // 省略掉一部分 gdb 的输出
- 0x00007fff7beaa78a in ?? () from /usr/lib/system/libsystem_kernel.dylib
- (gdb) b ngx_http_static_module.c:77
- Breakpoint 1 at 0x10183d7ad: file src/http/modules/ngx_http_static_module.c, line 77.
- (gdb) c
- Continuing.
-
- Breakpoint 1, ngx_http_static_handler (r=0x7ff649000450)
- at src/http/modules/ngx_http_static_module.c:77
- 77 last = ngx_http_map_uri_to_path(r, &path, &root, 0);
- (gdb) print r->uri
- $1 = {len = 11, data = 0x7ff649001173 "/index.html"}
- (gdb) next
- 78 if (last == NULL) {
- (gdb) print path
- $2 = {len = 33, data = 0x7ff64900117f "/usr/local/nginx/html/index.html"}
- (gdb)
这个期望是从 clion 等 ide 来调试 worker process
但是实际在 使用的过程中失败了
- [Thread debugging using libthread_db enabled]
- Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
-
- Breakpoint 1, ngx_start_worker_processes (cycle=0x1f757d0, n=1, type=-3) at src/os/unix/ngx_process_cycle.c:359
- 359 ngx_spawn_process(cycle, ngx_worker_process_cycle,
- (gdb) set follow-fork-mode child
- (gdb) show follow-fork-mode
- Debugger response to a program call of fork or vfork is "child".
- [Attaching after Thread 0x7f3055667700 (LWP 10253) fork to child process 10260]
- [New inferior 2 (process 10260)]
- [Detaching after fork from parent process 10253]
- [Inferior 1 (process 10253) detached]
- [Thread debugging using libthread_db enabled]
- Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
在原有的体系中 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" 为父进程的处理, 更新为子进程的处理, 然后 重新编译 调试即可
- switch (pid) {
-
- case -1:
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
- "fork() failed while spawning \"%s\"", name);
- ngx_close_channel(ngx_processes[s].channel, cycle->log);
- return NGX_INVALID_PID;
-
- case 0:
- // ngx_parent = ngx_pid;
- // ngx_pid = ngx_getpid();
- // proc(cycle, data);
- break;
-
- default:
- ngx_parent = ngx_pid;
- ngx_pid = ngx_getpid();
- proc(cycle, data);
- break;
- }
运行时调试的情况如下图
呵呵 以上不过是介绍了一些 tricks 而已
完