PHP - 由pcntl_fork启动的杀死子进程

时间:2009-11-12 09:51:25

标签: php linux posix

我正在使用pcntl_fork启动子进程以通过SMTP发送电子邮件。

子进程使用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 个答案:

答案 0 :(得分:5)

您需要如上所述等待它,或者使用posix_setsid

使子进程与父进程分离

答案 1 :(得分:4)

如果你有僵尸孩子,这意味着你不是wait他们。不是PHP专家,但系统调用是waitpid(2)。例如调用

waitpid(-1, NULL, WNOHANG);

每隔一段时间,或每当你得到SIGCHILD时。每次通话最多可以获得一个僵尸。如果没有外出的孩子,WNOHANG立即返回,而不是阻止。

wait手册页有一个很好的笔记部分,介绍了这一切是如何运作的......

答案 2 :(得分:1)

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

然后我会将电子邮件发送到本地中继,然后将其排队并尽快发送给收件人。

将它发送到本地中继的好处是你可以配置它用于退回电子邮件和其他回复。

关于已解散的问题,据我所知,SIGKILL是一种非常难以排除进程的方法,您是否尝试过(SIGSTOP或SIGTSTP)?

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

要完成彼得的回答,请查看pcntl_waitpid

杀人后只需要这样做: pcntl_waitpid($pid)