2009-11-12 218 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)