2009-11-12 219 views
7

我正在使用pcntl_fork启动子进程通过SMTP发送邮件。PHP - 杀死pcntl_fork启动的子进程

子进程使用PEAR Mail包发送邮件,但麻烦在于,如果远程服务器没有响应该进程,只是运行永远等待响应,而不管在php中设置了任何时间限制。 INI。

为了解决这个问题,我使用pcntl_alarm功能30秒杀死子进程,如果它仍在运行后触发功能。

function handlesig($sig) { 
    global $pid,$node,$resend; 
    posix_kill($pid,SIGKILL); 
    mysql_query("insert into log (event) values ('Timed out!')"); 
} 

当我杀子过程中,虽然我留下了在系统上已不存在的过程。

是否有不同的信号,我应该使用仍会强制子过程无需等待连接(因为连接写不完)死,避免僵尸进程的积累?

回答

5

您需要等待它如上所述,或使子进程与父母分离使用posix_setsid

1

此问题的正常解决方案是使用一个良好配置的本地主机中继。 我常规做的是设置一个本地主机,使用后缀。

然后我也会发送电子邮件到本地中继,哪个队列,并将其尽快发送给收件人越好。

它发送到本地中继的好处是,你可以配置它反弹的电子邮件和其他answeres。

对于你的问题有关解散的,据我所知是SIGKILL为书亭下来的过程非常硬的方法,你尝试(SIGSTOP或SIGTSTP)?

+0

我发送可怕的原因通过PHP是如此,我可以得到响应,并适当地处理它的成功/软反弹/硬反弹。 SIGTERM和SIGKILL是我知道的唯一信号,而SIGTERM不起作用,所以我使用了SIGKILL。我将尝试SIGSTOP/SIGTSTP。 – Tim 2009-11-12 16:41:31

+0

嗯,我个人会在2个独立的脚本中做到这一点。一个用于通过本地smtp服务发送处理反弹的secound,一种自动弹出/获取脚本,用于处理反弹和成功。 这样做的一个原因是将邮件传递到smtp的php脚本不会阻塞网络服务器孩子。例如,如果您最多有20个孩子,并且每个孩子正在开始与外部资源的连接,则在孩子再次被释放之前,没有其他服务可用。 – user207675 2009-11-13 07:29:02

1
exec(PATH_TO_PHP . " email_script.php $params > /dev/null 2>&1 &"); 

这样,家长不会等待孩子的回应,而且您没有僵尸。在email_script.php中处理您的电子邮件发送并将响应记录到文件中,您可以从父文件中分析该文件,或者不从中分析。

4

如果你有孩子的僵尸,这意味着你没有wait荷兰国际集团为他们。不是PHP专家,但系统调用是waitpid(2)。例如致电

waitpid(-1, NULL, WNOHANG); 

每隔一会儿或每当你得到SIGCHILD。每个电话将收获一个僵尸。 WNOHANG可以立即返回,而不会阻止没有孩子的孩子。

wait手册页有这一切是如何工作的一个很好的注释部分...

1

要完成彼得anwser,看看pcntl_waitpid

只需要击杀之后: pcntl_waitpid($pid)