http://bbs.chinaunix.net/viewthread.php?tid=1251434==================
lighttpd 采用 多进程 的工作模式,watcher 创建 workers 并且监控 workers 的退出。
watcher 循环创建 worker, 子进程 被创建后跳出循环做自己的工作。
当创建够 子进程 后,父进程 调用 wait() 等待有 子进程退出。
当父进程wait()中收到信号 SIGHUP,通知进程组的所有成员。
当服务器被关闭,父进程kill所有子进程,做清理工作,退出循环。
==================
版本: 1.4.27
<server.c>
=================
/// watcher 创建并监控 workers 工作
#ifdef HAVE_FORK
/* start watcher and workers */
num_childs = srv->srvconf.max_worker; // num_childs,需要创建的 worker 数量
if (num_childs > 0) {
int child = 0; // child 是一个 flag, 为0是watcher(父进程),为1是worker(子进程)
while (!child && !srv_shutdown && !graceful_shutdown) { // 如果是父进程,且服务器没有被关闭
if (num_childs > 0) { // num_childs>0, fork()创建子进程
switch (fork()) {
case -1:
return -1;
case 0: // 子进程,置child为1。退出循环。
child = 1;
break;
default: // 父进程,孩子数减1
num_childs--;
break;
}
} else { // num_childs=0, 子进程已经创建完了,父进程wait()等待有子进程退出
int status;
if (-1 != wait(&status)) { // 有子进程退出,num_childs++
/**
* one of our workers went away
*/
num_childs++;
} else { // wait 返回错误 (-1)
switch (errno) {
case EINTR: // wait()被中断打断
/**
* if we receive a SIGHUP we have to close our logs ourself as we don't
* have the mainloop who can help us here
*/
if (handle_sig_hup) { // 收到 SIGHUP, 关闭日志,通知进程组的所有进程
handle_sig_hup = 0;
log_error_cycle(srv);
/**
* forward to all procs in the process-group
*
* we also send it ourself
*/
if (!forwarded_sig_hup) {
forwarded_sig_hup = 1;
kill(0, SIGHUP); // pid=0 通知进程组所有成员
}
}
break;
default:
break;
}
}
}
}
/**
* for the parent this is the exit-point
*/
/// 服务器被关闭。通知进程组所有成员
/// 父进程只在这时才退出循环
if (!child) {
/**
* kill all children too
*/
if (graceful_shutdown) {
kill(0, SIGINT);
} else if (srv_shutdown) {
kill(0, SIGTERM);
}
// 清理工作
log_error_close(srv);
network_close(srv);
connections_free(srv);
plugins_free(srv);
server_free(srv);
return 0;
}
}
#endif