0

cgi 呼び出しからバックグラウンド プロセスをフォークしたい。httpd 呼び出しがすぐに戻り、残りのものが実行され続けるように

これは、新しいマシンに移行するまでずっと機能していました

............
## Close the http connection so that the remote client returns
close STDOUT;
close STDERR;
POSIX::setsid();
fork() && exit;
do_job();
.........

現在、新しいマシンでは、同じコードが do_job() Perl を実行することはありません。httpd のバージョンは同じです (カーネルのマイナー アップグレードがあります)。

今、コードを次のように変更しました

..........
open(STDOUT,">/dev/null");
open(STDERR,">/dev/null");
POSIX::setsid();
fork() && exit;
do_job();
.........

これは機能しますが、理由はわかりません

4

2 に答える 2

1

最初のコードが機能する理由についてはよくわかりません。ただし、常にfork()の後にsetsidを配置する必要があります。あなたがこれをした後にそれがうまくいかないかどうか私に知らせてください。

すべてのプロセスグループは一意のセッションにあります。(プロセスが作成されると、その親のセッションのメンバーになります。)慣例により、セッションのセッションIDは、セッションリーダーと呼ばれるセッションの最初のメンバーのプロセスIDと同じです。プロセスは、システムコールgetsid()を使用してセッションのIDを見つけます。

新しいセッションはによって作成されます

pid = setsid();

これは、現在のプロセスがプロセスグループリーダーでない場合にのみ許可されます。

その理由を説明させてください。プロセスグループリーダーまたはセッションリーダーの場合、プロセスグループとセッションIDは、それらを作成するプロセスのプロセスIDから初期化されることを理解する必要があると想定します(つまり、セッションリーダーの場合はpid == sidであり、プロセスの場合はリードします)。グループリーダーpid==pgid)。さらに、プロセスグループはセッション間を移動できません。

つまり、プロセスグループリーダーであり、新しいセッションの作成が許可されると、sidとpgidがpidに設定され、古いプロセスグループの他のプロセスが奇妙な状態になります。プロセスグループリーダーが突然は別のセッションにあり、それ自体がそうである可能性があります。そしてそれは許されないので、EPERMはカーネルによって返されます。

これで、セッションでもプロセスグループリーダーでもなくなったときにfork()を実行すると、そのようなグループには他のプロセスがないため、sidとpgidをpidに設定しても安全です。

次のリンクが役立つ場合があります。

セッションとプロセスグループ

Linuxカーネル:プロセス

于 2013-01-28T08:57:06.730 に答える
0

この種の作業を処理する外部キューの使用をお勧めします。いくつかの CPAN モジュールを使用して、Queue::DBIや Gearman などの機能を取得できます。

于 2013-01-28T08:29:28.287 に答える