nginx的网络模型是,master进程,即daemon进程,负责listen+bind,所有子进程都监听80端口,注册监听fd的读事件,即accept事件。
多进程调试方法
sudo gdb ./objs/nginxr -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
info inferiors
follow-fork-mode detach-on-fork 说明
parent on 只调试主进程(GDB默认)
child on 只调试子进程
parent off 同时调试两个进程,gdb跟主进程,子进程block在fork位置
child off 同时调试两个进程,gdb跟子进程,主进程block在fork位置
set follow-fork-mode child
set detach-on-fork off
catch fork
b ngx_configure_listening_sockets
b ngx_connection.c:794
b ngx_set_inherited_sockets
b ngx_create_listening
b ngx_open_listening_sockets
b ngx_connection.c:591
b ngx_close_listening_sockets
b ngx_event_accept
b ngx_epoll_init
b ngx_epoll_add_event
b ngx_epoll_del_event
b ngx_epoll_add_connection
b ngx_epoll_del_connection
b ngx_epoll_process_events
b ngx_daemon.c:29
程序hang住以后可以通过sudo kill -9 master进程号,然后inferior worker进程号来
终止父进程,开启子进程调试
liuwb@ubuntu:~/Desktop/code/nginx-code$ ps ax | grep nginx
6972 pts/6 S+ 0:00 sudo gdb ./objs/nginx
6973 pts/6 S+ 0:00 gdb ./objs/nginx
6981 ? Ss 0:00 nginx: master process /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
6982 ? S 0:00 nginx: worker process
6983 ? S 0:00 nginx: worker process
liuwb@ubuntu:~/Desktop/code/nginx-code$ netstat -antp | grep 80
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 6982/nginx: worker
tcp 0 0 192.168.235.128:22 192.168.235.1:58019 ESTABLISHED -
第一个worker listen了80端口
ngx_worker_process_init(cycle, worker);
for (i = 0; cycle->modules[i]; i++) {
if (cycle->modules[i]->init_process) {
if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
/* fatal */
exit(2);
}
}
}
ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT, ngx_channel_handler)
ngx_add_event(ev, event, 0)
ngx_event_module_t ngx_epoll_module_ctx = {
&epoll_name,
ngx_epoll_create_conf, /* create configuration */
ngx_epoll_init_conf, /* init configuration */
{
ngx_epoll_add_event, /* add an event */
ngx_epoll_del_event, /* delete an event */
ngx_epoll_add_event, /* enable an event */
ngx_epoll_del_event, /* disable an event */
ngx_epoll_add_connection, /* add an connection */
ngx_epoll_del_connection, /* delete an connection */
#if (NGX_HAVE_EVENTFD)
ngx_epoll_notify, /* trigger a notify */
#else
NULL, /* trigger a notify */
#endif
ngx_epoll_process_events, /* process the events */
ngx_epoll_init, /* init the events */
ngx_epoll_done, /* done the events */
}
};
ngx_event_actions = ngx_epoll_module_ctx.actions;
#define ngx_process_events ngx_event_actions.process_events
#define ngx_done_events ngx_event_actions.done
#define ngx_add_event ngx_event_actions.add
#define ngx_del_event ngx_event_actions.del
#define ngx_add_conn ngx_event_actions.add_conn
#define ngx_del_conn ngx_event_actions.del_conn
#define ngx_notify ngx_event_actions.notify
#define ngx_add_timer ngx_event_add_timer
#define ngx_del_timer ngx_event_del_timer
Breakpoint 2, ngx_epoll_init (cycle=0x72d530, timer=0) at src/event/modules/ngx_epoll_module.c:327
327 epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
(gdb) bt
#0 ngx_epoll_init (cycle=0x72d530, timer=0) at src/event/modules/ngx_epoll_module.c:327
#1 0x0000000000441f71 in ngx_event_process_init (cycle=0x72d530) at src/event/ngx_event.c:620
#2 0x0000000000450bec in ngx_worker_process_init (cycle=0x72d530, worker=0) at src/os/unix/ngx_process_cycle.c:902
#3 0x00000000004503f1 in ngx_worker_process_cycle (cycle=0x72d530, data=0x0) at src/os/unix/ngx_process_cycle.c:734
#4 0x000000000044cca6 in ngx_spawn_process (cycle=0x72d530, proc=0x4503b0 <ngx_worker_process_cycle>, data=0x0,
name=0x4dcfcb "worker process", respawn=-3) at src/os/unix/ngx_process.c:198
#5 0x000000000044f2e1 in ngx_start_worker_processes (cycle=0x72d530, n=2, type=-3) at src/os/unix/ngx_process_cycle.c:358
#6 0x000000000044e894 in ngx_master_process_cycle (cycle=0x72d530) at src/os/unix/ngx_process_cycle.c:130
#7 0x000000000040ba95 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:367
ngx_event_core_module的init_process方法,调用ngx_epoll_module的
module = cycle->modules[m]->ctx;
module->actions.init(cycle, ngx_timer_resolution)
在成为后台进程前
(gdb) bt
#0 ngx_create_listening (cf=0x7fffffffe1e0, sockaddr=0x731f30, socklen=16) at src/core/ngx_connection.c:22
#1 0x00000000004575d0 in ngx_http_add_listening (cf=0x7fffffffe1e0, addr=0x731f30) at src/http/ngx_http.c:1707
#2 0x00000000004574a4 in ngx_http_init_listening (cf=0x7fffffffe1e0, port=0x731ec0) at src/http/ngx_http.c:1658
#3 0x0000000000456c79 in ngx_http_optimize_servers (cf=0x7fffffffe1e0, cmcf=0x730680, ports=0x731e98) at src/http/ngx_http.c:1412
#4 0x0000000000454ab6 in ngx_http_block (cf=0x7fffffffe1e0, cmd=0x6fc4a0 <ngx_http_commands>, conf=0x72e550)
at src/http/ngx_http.c:333
#5 0x000000000042f262 in ngx_conf_handler (cf=0x7fffffffe1e0, last=1) at src/core/ngx_conf_file.c:427
#6 0x000000000042eda1 in ngx_conf_parse (cf=0x7fffffffe1e0, filename=0x72d6f8) at src/core/ngx_conf_file.c:283
#7 0x000000000042b004 in ngx_init_cycle (old_cycle=0x7fffffffe3b0) at src/core/ngx_cycle.c:274
#8 0x000000000040b6d0 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:276
Breakpoint 9, ngx_open_listening_sockets (cycle=0x72d530) at src/core/ngx_connection.c:591
591 if (listen(s, ls[i].backlog) == -1) {
(gdb) p s
$2 = 7
(gdb) p i
$3 = 0
(gdb) p ls[i].backlog
$4 = 511
(gdb) bt
#0 ngx_open_listening_sockets (cycle=0x72d530) at src/core/ngx_connection.c:591
#1 0x000000000042c299 in ngx_init_cycle (old_cycle=0x7fffffffe3b0) at src/core/ngx_cycle.c:609
#2 0x000000000040b6d0 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:276
gdb) p ls[i].fd
$6 = 7
(gdb) p ls[i].backlog
$7 = 511
(gdb)
794 if (listen(ls[i].fd, ls[i].backlog) == -1) {
(gdb) bt
#0 ngx_configure_listening_sockets (cycle=0x72d530) at src/core/ngx_connection.c:794
#1 0x000000000042c2be in ngx_init_cycle (old_cycle=0x7fffffffe3b0) at src/core/ngx_cycle.c:614
#2 0x000000000040b6d0 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:276
listen函数被调用了2次,/第二次调用写的注释* change backlog via listen() */
创建daemon线程
liuwb@ubuntu:~/Desktop/code/nginx-code$ ps ax | grep nginx
13279 pts/6 S+ 0:00 sudo gdb ./objs/nginx
13280 pts/6 S+ 0:01 gdb ./objs/nginx
13376 pts/6 t 0:00 /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
父进程
13470 pts/6 t 0:00 /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
子进程
13476 pts/7 S+ 0:00 grep --color=auto nginx
liuwb@ubuntu:~/Desktop/code/nginx-code$ netstat -antp | grep 80
(No info could be read for "-p": geteuid()=1000 but you should be root.)
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 192.168.235.128:22 192.168.235.1:58019 ESTABLISHED -
创建worker进程
(gdb) bt
#0 0x00007ffff7024025 in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/x86_64/../fork.c:130
#1 0x000000000044cbfd in ngx_spawn_process (cycle=0x72d530, proc=0x4503b0 <ngx_worker_process_cycle>, data=0x0,
name=0x4dcfcb "worker process", respawn=-3) at src/os/unix/ngx_process.c:186
#2 0x000000000044f2e1 in ngx_start_worker_processes (cycle=0x72d530, n=2, type=-3) at src/os/unix/ngx_process_cycle.c:358
#3 0x000000000044e894 in ngx_master_process_cycle (cycle=0x72d530) at src/os/unix/ngx_process_cycle.c:130
#4 0x000000000040ba95 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:367
liuwb@ubuntu:~/Desktop/code/nginx-code$ ps ax | grep nginx
13279 pts/6 S+ 0:00 sudo gdb ./objs/nginx
13280 pts/6 S+ 0:02 gdb ./objs/nginx
13376 pts/6 t 0:00 /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
13470 ? ts 0:00 nginx: master process /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
daemon进程
13492 ? t 0:00 nginx: master process /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
13499 pts/7 S+ 0:00 grep --color=auto nginx
liuwb@ubuntu:~/Desktop/code/nginx-code$ netstat -antp | grep 80
(No info could be read for "-p": geteuid()=1000 but you should be root.)
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 192.168.235.128:22 192.168.235.1:58019 ESTABLISHED -
继续运行子进程:
liuwb@ubuntu:~/Desktop/code/nginx-code$ ps ax | grep nginx
13279 pts/6 S 0:00 sudo gdb ./objs/nginx
13280 pts/6 S 0:04 gdb ./objs/nginx
13376 pts/6 t+ 0:00 /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
13470 ? ts 0:00 nginx: master process /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
13492 ? S 0:00 nginx: worker process
13536 pts/7 S+ 0:00 grep --color=auto nginx
liuwb@ubuntu:~/Desktop/code/nginx-code$ netstat -antp | grep 80
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 13492/nginx: worker
tcp 0 0 192.168.235.128:22 192.168.235.1:58019 ESTABLISHED -
liuwb@ubuntu:~/Desktop/code/nginx-code$ sudo cat /proc/13492/status
Name: nginx
State: S (sleeping)
Tgid: 13492
Ngid: 0
Pid: 13492
PPid: 13470
TracerPid: 13280
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
liuwb@ubuntu:~/Desktop/code/nginx-code$ sudo cat /proc/13492/stack
[<ffffffff81230e0c>] ep_poll+0x26c/0x350
[<ffffffff81231ff5>] SyS_epoll_wait+0xb5/0xe0
[<ffffffff817b668d>] system_call_fastpath+0x16/0x1b
[<ffffffffffffffff>] 0xffffffffffffffff
hung在了epoll_wait,即ngx_epoll_process_events
父进程,挂在信号处理的地方
liuwb@ubuntu:~/Desktop/code/nginx-code$ sudo cat /proc/14206/stack
[<ffffffff81085a1d>] sigsuspend+0x3d/0x80
[<ffffffff81085aa0>] SyS_rt_sigsuspend+0x40/0x60
[<ffffffff817b668d>] system_call_fastpath+0x16/0x1b
[<ffffffffffffffff>] 0xffffffffffffffff
Breakpoint 14, ngx_epoll_init (cycle=0x72d530, timer=0) at src/event/modules/ngx_epoll_module.c:327
327 epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
(gdb) bt
#0 ngx_epoll_init (cycle=0x72d530, timer=0) at src/event/modules/ngx_epoll_module.c:327
#1 0x0000000000441f71 in ngx_event_process_init (cycle=0x72d530) at src/event/ngx_event.c:620
#2 0x0000000000450bec in ngx_worker_process_init (cycle=0x72d530, worker=0) at src/os/unix/ngx_process_cycle.c:902
#3 0x00000000004503f1 in ngx_worker_process_cycle (cycle=0x72d530, data=0x0) at src/os/unix/ngx_process_cycle.c:734
#4 0x000000000044cca6 in ngx_spawn_process (cycle=0x72d530, proc=0x4503b0 <ngx_worker_process_cycle>, data=0x0,
name=0x4dcfcb "worker process", respawn=-3) at src/os/unix/ngx_process.c:198
#5 0x000000000044f2e1 in ngx_start_worker_processes (cycle=0x72d530, n=2, type=-3) at src/os/unix/ngx_process_cycle.c:358
#6 0x000000000044e894 in ngx_master_process_cycle (cycle=0x72d530) at src/os/unix/ngx_process_cycle.c:130
#7 0x000000000040ba95 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:367
下面是添加listen fd的读事件,触发了才会调用accept
Breakpoint 15, ngx_epoll_add_event (ev=0x799e40, event=8193, flags=0) at src/event/modules/ngx_epoll_module.c:587
587 c = ev->data;
(gdb) bt
#0 ngx_epoll_add_event (ev=0x799e40, event=8193, flags=0) at src/event/modules/ngx_epoll_module.c:587
#1 0x0000000000442985 in ngx_event_process_init (cycle=0x72d530) at src/event/ngx_event.c:857
#2 0x0000000000450bec in ngx_worker_process_init (cycle=0x72d530, worker=0) at src/os/unix/ngx_process_cycle.c:902
#3 0x00000000004503f1 in ngx_worker_process_cycle (cycle=0x72d530, data=0x0) at src/os/unix/ngx_process_cycle.c:734
#4 0x000000000044cca6 in ngx_spawn_process (cycle=0x72d530, proc=0x4503b0 <ngx_worker_process_cycle>, data=0x0,
name=0x4dcfcb "worker process", respawn=-3) at src/os/unix/ngx_process.c:198
#5 0x000000000044f2e1 in ngx_start_worker_processes (cycle=0x72d530, n=2, type=-3) at src/os/unix/ngx_process_cycle.c:358
#6 0x000000000044e894 in ngx_master_process_cycle (cycle=0x72d530) at src/os/unix/ngx_process_cycle.c:130
#7 0x000000000040ba95 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:367
ngx_channel = ngx_processes[s].channel[1];
ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT, ngx_channel_handler)
管道注册读事件,和父进程通信
(gdb) bt
#0 ngx_epoll_add_event (ev=0x799ea0, event=8193, flags=0) at src/event/modules/ngx_epoll_module.c:587
#1 0x000000000044c40b in ngx_add_channel_event (cycle=0x72d530, fd=8, event=8193, handler=0x45116a <ngx_channel_handler>)
at src/os/unix/ngx_channel.c:233
#2 0x0000000000450da2 in ngx_worker_process_init (cycle=0x72d530, worker=0) at src/os/unix/ngx_process_cycle.c:938
#3 0x00000000004503f1 in ngx_worker_process_cycle (cycle=0x72d530, data=0x0) at src/os/unix/ngx_process_cycle.c:734
#4 0x000000000044cca6 in ngx_spawn_process (cycle=0x72d530, proc=0x4503b0 <ngx_worker_process_cycle>, data=0x0,
name=0x4dcfcb "worker process", respawn=-3) at src/os/unix/ngx_process.c:198
#5 0x000000000044f2e1 in ngx_start_worker_processes (cycle=0x72d530, n=2, type=-3) at src/os/unix/ngx_process_cycle.c:358
#6 0x000000000044e894 in ngx_master_process_cycle (cycle=0x72d530) at src/os/unix/ngx_process_cycle.c:130
#7 0x000000000040ba95 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:367
子进程准备进入循环,进入循环前,2次到了这里,说明第1次epoll_wait返回了
(gdb) bt
#0 ngx_epoll_process_events (cycle=0x72d530, timer=18446744073709551615, flags=1) at src/event/modules/ngx_epoll_module.c:797
#1 0x00000000004414c8 in ngx_process_events_and_timers (cycle=0x72d530) at src/event/ngx_event.c:242
#2 0x00000000004504a5 in ngx_worker_process_cycle (cycle=0x72d530, data=0x0) at src/os/unix/ngx_process_cycle.c:753
#3 0x000000000044cca6 in ngx_spawn_process (cycle=0x72d530, proc=0x4503b0 <ngx_worker_process_cycle>, data=0x0,
name=0x4dcfcb "worker process", respawn=-3) at src/os/unix/ngx_process.c:198
#4 0x000000000044f2e1 in ngx_start_worker_processes (cycle=0x72d530, n=2, type=-3) at src/os/unix/ngx_process_cycle.c:358
#5 0x000000000044e894 in ngx_master_process_cycle (cycle=0x72d530) at src/os/unix/ngx_process_cycle.c:130
#6 0x000000000040ba95 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:367