+ if ($pid) { # parent
+ print KID_TO_WRITE @data;
+ close(KID_TO_WRITE) || warn "kid exited $?";
+
+ } else { # child
+ ($EUID, $EGID) = ($UID, $GID);
+ exec($program, @options, @args)
+ || die "can't exec program: $!";
+ # NOTREACHED
+ }
+
+It is very easy to dead-lock a process using this form of open(), or
+indeed with any use of pipe() with multiple subprocesses. The
+example above is "safe" because it is simple and calls exec(). See
+L</"Avoiding Pipe Deadlocks"> for general safety principles, but there
+are extra gotchas with Safe Pipe Opens.
+
+In particular, if you opened the pipe using C<open FH, "|-">, then you
+cannot simply use close() in the parent process to close an unwanted
+writer. Consider this code:
+
+ my $pid = open(WRITER, "|-"); # fork open a kid
+ defined($pid) || die "first fork failed: $!";
+ if ($pid) {
+ if (my $sub_pid = fork()) {
+ defined($sub_pid) || die "second fork failed: $!";
+ close(WRITER) || die "couldn't close WRITER: $!";
+ # now do something else...
+ }
+ else {
+ # first write to WRITER
+ # ...
+ # then when finished
+ close(WRITER) || die "couldn't close WRITER: $!";
+ exit(0);
+ }
+ }
+ else {
+ # first do something with STDIN, then
+ exit(0);
+ }
+
+In the example above, the true parent does not want to write to the WRITER
+filehandle, so it closes it. However, because WRITER was opened using
+C<open FH, "|-">, it has a special behavior: closing it calls
+waitpid() (see L<perlfunc/waitpid>), which waits for the subprocess
+to exit. If the child process ends up waiting for something happening
+in the section marked "do something else", you have deadlock.
+
+This can also be a problem with intermediate subprocesses in more
+complicated code, which will call waitpid() on all open filehandles
+during global destruction--in no predictable order.
+
+To solve this, you must manually use pipe(), fork(), and the form of
+open() which sets one file descriptor to another, as shown below:
+
+ pipe(READER, WRITER) || die "pipe failed: $!";
+ $pid = fork();
+ defined($pid) || die "first fork failed: $!";
+ if ($pid) {
+ close READER;
+ if (my $sub_pid = fork()) {
+ defined($sub_pid) || die "first fork failed: $!";
+ close(WRITER) || die "can't close WRITER: $!";
+ }
+ else {
+ # write to WRITER...
+ # ...
+ # then when finished
+ close(WRITER) || die "can't close WRITER: $!";
+ exit(0);
+ }
+ # write to WRITER...
+ }
+ else {
+ open(STDIN, "<&READER") || die "can't reopen STDIN: $!";
+ close(WRITER) || die "can't close WRITER: $!";
+ # do something...
+ exit(0);