Re: [PATCH] Attempt at improving the perlipc docs
[email protected] (Maik Hentsche)
| Newsgroups | perl.perl5.porters |
|---|---|
| Message-ID | <[email protected]> |
Hi, after being back from vacation I see no further improvement suggestions for my doc patch. I implemented those I did receive before. Please find the updated patch attached. It applies to the current git HEAD. For those of you who do not fully remember the topic here comes a description of the issue I'm trying to solve. I was recently confused by the way signal handlers using wait() behave in collaboration with qx() or system(). When you have a signal handler for SIGCHLD that calls wait() and use qx() or system() in your parent, the signal handler will be called. Yet, because qx/system already wait()ed for their child the wait in the signal handler would block. I doubt everyone will understand this in the first place. Thus, I wrote an improvement for the documentation to tell people about this issue. so long Maik -- Maik Hentsche <[email protected]> Tel.:0177/6875926 http://chemnitzer.linux-tage.de
0001-Improve-documentation-for-SIGCHLD-handling.patch
(text/x-patch, 2.3 KB)
diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod
index ccffcdb..69cc64a 100644
--- a/pod/perlfunc.pod
+++ b/pod/perlfunc.pod
@@ -6747,6 +6747,10 @@ When C<system>'s arguments are executed indirectly by the shell,
results and return codes are subject to its quirks.
See L<perlop/"`STRING`"> and L</exec> for details.
+Since C<system> does a C<fork> and C<wait> it may affect C<SIGCHLD> handler.
+See L<perlipc> for details.
+
+
=item syswrite FILEHANDLE,SCALAR,LENGTH,OFFSET
X<syswrite>
@@ -7606,6 +7610,9 @@ and C<${^CHILD_ERROR_NATIVE}>.
Note that a return value of C<-1> could mean that child processes are
being automatically reaped, as described in L<perlipc>.
+If you use wait in your handler for $SIG{CHLD} it may accidently wait for the
+child created by qx() or system(). See L<perlipc> for details.
+
=item waitpid PID,FLAGS
X<waitpid>
diff --git a/pod/perlipc.pod b/pod/perlipc.pod
index 4f6c0f0..319989d 100644
--- a/pod/perlipc.pod
+++ b/pod/perlipc.pod
@@ -150,6 +150,42 @@ or better still:
$SIG{CHLD} = \&REAPER;
# do something that forks...
+Note: qx(), system() and some modules for calling external commands do a
+fork() and wait() for the result. Thus, your signal handler (REAPER in the
+example) will be called. Since wait() was already called by system() or qx()
+the wait() in the signal handler will not see any more zombies and therefore
+block.
+
+The best way to prevent this issue is to use waitpid as in the following
+example.
+
+ use POSIX ":sys_wait_h"; # for nonblocking read
+
+ my %children;
+
+ $SIG{CHLD} = sub {
+ # don't change $! and $? outside handler
+ local ($!,$?);
+ my $pid = waitpid(-1, WNOHANG);
+ return if $pid == -1;
+ return unless defined $children{$pid};
+ delete $children{$pid};
+ cleanup_child($pid, $?);
+ };
+
+ while(1){
+ my $pid = fork();
+ if ($pid == 0){
+ ...
+ exit 0;
+ } else {
+ $children{$pid}=1;
+ ...
+ system($command);
+ ...
+ }
+ }
+
Signal handling is also used for timeouts in Unix, While safely
protected within an C<eval{}> block, you set a signal handler to trap
alarm signals and then schedule to have one delivered to you in some