+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);
+ }
+
+Since Perl 5.8.0, you can also use the list form of C<open> for pipes.
+This is preferred when you wish to avoid having the shell interpret
+metacharacters that may be in your command string.
+
+So for example, instead of using:
+
+ open(PS_PIPE, "ps aux|") || die "can't open ps pipe: $!";
+
+One would use either of these:
+
+ open(PS_PIPE, "-|", "ps", "aux")
+ || die "can't open ps pipe: $!";
+
+ @ps_args = qw[ ps aux ];
+ open(PS_PIPE, "-|", @ps_args)
+ || die "can't open @ps_args|: $!";
+
+Because there are more than three arguments to open(), forks the ps(1)
+command I<without> spawning a shell, and reads its standard output via the
+C<PS_PIPE> filehandle. The corresponding syntax to I<write> to command
+pipes is to use C<"|-"> in place of C<"-|">.
+
+This was admittedly a rather silly example, because you're using string
+literals whose content is perfectly safe. There is therefore no cause to
+resort to the harder-to-read, multi-argument form of pipe open(). However,
+whenever you cannot be assured that the program arguments are free of shell
+metacharacters, the fancier form of open() should be used. For example: