2 {
3 printf("Syntax OK\n");
4 }
3 /*
4 * 忽略和终端读写有关的信号
5 */
6 #ifdef SIGTTOU
7 signal(SIGTTOU, SIG_IGN);
8 #endif
9 #ifdef SIGTTIN
10 signal(SIGTTIN, SIG_IGN);
11 #endif
12 #ifdef SIGTSTP
13 signal(SIGTSTP, SIG_IGN);
14 #endif
15 if (0 != fork()) /* 产生子进程,父进程退出 */
16 exit(0);
17 if (-1 == setsid())/* 设置子进程的设置ID */
18 exit(0);
19 signal(SIGHUP, SIG_IGN);/* 忽略SIGHUP信号 */
20 if (0 != fork())/* 再次产生子进程,父进程退出 */
21 exit(0);
22 if (0 != chdir("/"))/* 更改工作目录为根目录 */
23 exit(0);
24 }
3 * 也就是用于接受处理用户的连接的进程。而当前的主进程将
4 * 成为watcher,主要工作就是监视workers的工作状态,
5 * 当有worker因为意外而退出时,产生新的worker。
6 * 在程序退出时,watcher负责停止所有的workers并清理资源。
7 */
8 int child = 0; //用来标记这个进程是子进程还是父进程。
9 //当子进程返回到这个while循环的开始的时候,由于标记
10 //进程是子进程,流程直接跳出while循环执行后面的程序。
11 //而对于父进程,则继续产生子进程。
12 while (!child && !srv_shutdown && !graceful_shutdown)
13 {
14 if (num_childs > 0) //watcher继续产生worker
15 {
16 switch (fork())
17 {
18 case -1: //出错
19 return -1;
20 case 0: //子进程进入这个case
21 child = 1;
22 break;
23 default: //父进程进入这个case
24 num_childs--;
25 break;
26 }
27 }
28 else //watcher
29 {
30 /**
31 * 当产生了足够的worker时,watcher就在这个while
32 * 中不断的循环。
33 * 一但发现有worker退出(进程死亡),立即产生新的worker。
34 * 如果发生错误并接受到SIGHUP信号,向所有的进程
35 *(父进程及其子进程)包括自己发送SIGHUP信号。
36 * 并退出。
37 */
38 int status;
39
40 if (-1 != wait(&status))
41 {
42 /**
43 * one of our workers went away
44 */
45 num_childs++;
46 }
47 else
48 {
49 switch (errno)
50 {
51 case EINTR:
52 /**
53 * if we receive a SIGHUP we have to close our
54 * logs ourself as we don't
55 * have the mainloop who can help us here
56 */
57 if (handle_sig_hup)
58 {
59 handle_sig_hup = 0;
61 log_error_cycle(srv);
63 /**
64 * forward to all procs in the process-group
65 * 向所有进程发送SIGHUP信号。(父进程及其子进程)
67 * we also send it ourself
68 */
69 if (!forwarded_sig_hup)
70 {
71 forwarded_sig_hup = 1;
72 kill(0, SIGHUP);
73 }
74 }
75 break;
76 default:
77 break;
78 }end of switch (errno)...
79 }//end of if (-1 != wait(&status)) ...
80 }//end of if (num_childs > 0)...
81 }// end of while(!child...
82
3 fdevent_handler handler; //事件处理函数指针
4 void *context;
5 handler_t r;
6 //获得下一个事件的标号
7 fd_ndx = fdevent_event_next_fdndx(srv->ev, fd_ndx);
8 //获得这个事件的具体类型。
9 revents = fdevent_event_get_revent(srv->ev, fd_ndx);
10 //获得事件对应的文件描述符
11 fd = fdevent_event_get_fd(srv->ev, fd_ndx);
12 //获得事件处理函数的指针
13 handler = fdevent_get_handler(srv->ev, fd);
14 //获得事件的环境
15 context = fdevent_get_context(srv->ev, fd);
16 /**
17 * 这里,调用请求的处理函数handler处理请求!
18 * 这才是重点中的重点!!
19 */
20 switch (r = (*handler) (srv, context, revents))
21 {
22 case HANDLER_FINISHED:
23 case HANDLER_GO_ON:
24 case HANDLER_WAIT_FOR_EVENT:
25 case HANDLER_WAIT_FOR_FD:
26 break;
27 case HANDLER_ERROR:
28 /*
29 * should never happen
30 */
31 SEGFAULT();
32 break;
33 default:
34 log_error_write(srv, __FILE__, __LINE__, "d", r);
35 break;
36 }
37 }while (—n > 0);
38