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