読者です 読者をやめる 読者になる 読者になる

SIGCHLD を SIG_IGN すると mail 関数が false を返す

PHP

以下のコードを実行すると mail 関数が false を返します。

<?php
pcntl_signal(SIGCHLD, SIG_IGN);
$ret = mail("user@example.com", "aaa", "bbb");
var_dump($ret);

ただし、実際にはメールは送信出来ており mail 関数が false を返すこと以外に特に問題はありません。

原因

SIGCHLD を SIG_IGN すると子プロセスがゾンビ化しなくなり、終了時に自動的に子プロセスの資源が解放されます。 が、その代わりに親プロセスで子プロセスの終了を補足できなくなります。

一方、php の mail 関数は、php 自体が SMTP をしゃべってメールを送信するわけではなく、php から sendmail コマンドを実行してメールを送信します(Windows 版だと phpSMTP をしゃべりますが)。

そのため、SIGCHLD を SIG_IGN すると sendmail コマンドの実行結果を php が補足出来なくなり(というか必ず失敗したことになり)、その結果 mail 関数が false を返すようになります。

configure--enable-sigchild

php のビルド時の configure--enable-sigchild をつけておくと、mail 関数(と exec などのプロセス実行関連の関数)の呼び出し時に SIGCHLD のシグナルハンドラを一時的に SIG_DFL に戻すようです。

BSD と Linux で動作が異なる?

SIGCHLD を SIG_IGN にした場合の動作は BSD と Linux で違っていたり Linux でもカーネル 2.4 と 2.6 で違っていたりするらしいので、多用しない方がいいかもしれません。