Perl:fork(),避免僵尸进程,以及 "No child processes" 错误
Perl: fork(), avoiding zombie processes, and "No child processes" error
我有一个 Perl 应用程序,几年来在 RH 系统上 运行 基本没有问题。在一个地方,我必须 运行 一个可能需要很多分钟才能完成的系统命令,所以我在子进程中执行此操作。整体结构是这样的:
$SIG{CHLD} = 'IGNORE'; # Ignore dead children, to avoid zombie processes
my $child = fork();
if ($child) { # Parent; return OK
$self->status_ok();
} else { # Child; run system command
# do a bunch of data retrieval, etc.
my $output;
my @command = # generate system command here
use IPC::System::Simple 'capture';
eval { $output = capture(@command); };
$self->log->error("Error running @command: $@") if $@;
# success: log $output, carry on
}
我们最近更改了一些基础架构,尽管不是以我预期的方式对此产生任何影响。 (仍然 运行ning 在 RH 上,仍然使用 nginx 等)但是,现在我们发现几乎 运行ning 这段代码的每个实例都会失败,记录 'Error running {command}: failed to start: "No child processes" at /path/to/code.pl'.
我环顾四周,无法找出正确的解决方案。有人建议将 $SIG{CHLD}
从 'IGNORE' 更改为 'DEFAULT',但我不得不担心僵尸进程。
是什么导致了 "No child processes" 错误,我们该如何解决?
There was a suggestion to change $SIG{CHLD} from 'IGNORE' to 'DEFAULT', but then I have to worry about zombie processes.
这不是真的。
僵尸进程是已经结束但尚未被其 parent 收割的进程。 parent 使用 wait
(2)、waitpid
(2) 或类似方法获得其 children。 capture
等待它的 child 结束,所以它不会留下任何僵尸。
事实上,您收到的错误来自 waitpid
。 capture
正在等待 child 结束以获取它并收集其错误代码,但是您指示 OS 在它完成后立即清理 child, waitpid
没有 child 可以收集,也没有错误代码可以收集。
要解决此问题,只需在调用 capture
之前放置 local $SIG{CHLD} = 'DEFAULT';
。
我有一个 Perl 应用程序,几年来在 RH 系统上 运行 基本没有问题。在一个地方,我必须 运行 一个可能需要很多分钟才能完成的系统命令,所以我在子进程中执行此操作。整体结构是这样的:
$SIG{CHLD} = 'IGNORE'; # Ignore dead children, to avoid zombie processes
my $child = fork();
if ($child) { # Parent; return OK
$self->status_ok();
} else { # Child; run system command
# do a bunch of data retrieval, etc.
my $output;
my @command = # generate system command here
use IPC::System::Simple 'capture';
eval { $output = capture(@command); };
$self->log->error("Error running @command: $@") if $@;
# success: log $output, carry on
}
我们最近更改了一些基础架构,尽管不是以我预期的方式对此产生任何影响。 (仍然 运行ning 在 RH 上,仍然使用 nginx 等)但是,现在我们发现几乎 运行ning 这段代码的每个实例都会失败,记录 'Error running {command}: failed to start: "No child processes" at /path/to/code.pl'.
我环顾四周,无法找出正确的解决方案。有人建议将 $SIG{CHLD}
从 'IGNORE' 更改为 'DEFAULT',但我不得不担心僵尸进程。
是什么导致了 "No child processes" 错误,我们该如何解决?
There was a suggestion to change $SIG{CHLD} from 'IGNORE' to 'DEFAULT', but then I have to worry about zombie processes.
这不是真的。
僵尸进程是已经结束但尚未被其 parent 收割的进程。 parent 使用 wait
(2)、waitpid
(2) 或类似方法获得其 children。 capture
等待它的 child 结束,所以它不会留下任何僵尸。
事实上,您收到的错误来自 waitpid
。 capture
正在等待 child 结束以获取它并收集其错误代码,但是您指示 OS 在它完成后立即清理 child, waitpid
没有 child 可以收集,也没有错误代码可以收集。
要解决此问题,只需在调用 capture
之前放置 local $SIG{CHLD} = 'DEFAULT';
。