继续对pgpool-II的child.c里面的 do_child函数进行分析,改动代码如下:
复制代码
/*
* child main loop
*/
void do_child(int unix_fd, int inet_fd)
{
……
for (;;)
{
……
/* perform accept() */
frontend = do_accept(unix_fd, inet_fd, &timeout);
/*added by gaojian begin*/
if (frontend==NULL)
{
pool_log("frontend is NULL");
}else{
pool_log("frontend is not NULL");
pool_log("I am %d", getpid());
}
/*added by gaojian end*/
if (frontend == NULL) /* connection request from frontend timed out */
{
/* check select() timeout */
if (connected && pool_config->child_life_time > 0 &&
timeout.tv_sec == 0 && timeout.tv_usec == 0)
{
pool_debug("child life %d seconds expired",
pool_config->child_life_time);
/*
* Doesn't need to call this. child_exit() calls it.
* send_frontend_exits();
*/
child_exit(2);
}
continue;
}
……
}
child_exit(0);
}
复制代码
重新编译运行后,开一个客户端,显示如下:
LOG: pid 16210: frontend is not NULL.
LOG: pid 16210: I am 16210
再开一个客户端,显示如下:
LOG: pid 16212: frontend is not NULL.
LOG: pid 16212: I am 16212
也就是说:开一个客户端,就会有一个child被唤醒
(通过do_accept函数,虽然大家都调用了do_accept函数,但是哪个被唤醒当有一个算法)
此时,kill -9 16210。然后在此客户端再执行sql文:
select * from a5;
显示:
postgres=#select * from a5;
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.
postgres=#
这是,再看pgpool后台,
LOG: pid 16216: frontend is not NULL.
LOG: pid 16216: I am 16216
这是因为 Attempting reset, 又唤醒了一个 子进程。
由此可以得到两个结论:
结论一:虽然所有的child都会调用 do_child,在 do_child里调用 do_accept,但是相当于大家都去申请,轮到谁来响应客户的请求,倒不一定。
结论二:如果某个child不幸挂掉了,为了继续响应同一个客户端,另一个child会被唤醒。
本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2012/07/31/2616769.html,如需转载请自行联系原作者