From: Mark-Jason Dominus Date: Thu, 18 Apr 2002 09:38:17 +0000 (-0400) Subject: [PATCH 5.7.3 docs] The question deals with a bug that was fixed X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=dfdf0730bd274f3c13984f18924d73cc14c99be9;p=p5sagit%2Fp5-mst-13.2.git [PATCH 5.7.3 docs] The question deals with a bug that was fixed Date: Thu, 18 Apr 2002 09:38:17 -0400 Message-ID: <20020418133817.22436.qmail@plover.com> Subject: [PATCH 5.7.3 docs] Backticks in void context are no longer inefficient From: Mark-Jason Dominus Date: Thu, 18 Apr 2002 09:54:50 -0400 Message-ID: <20020418135450.22999.qmail@plover.com> p4raw-id: //depot/perl@15992 --- diff --git a/pod/perlfaq8.pod b/pod/perlfaq8.pod index cc2f072..1ece0f2 100644 --- a/pod/perlfaq8.pod +++ b/pod/perlfaq8.pod @@ -680,50 +680,38 @@ there, and the old standard error shows up on the old standard out. =head2 Why doesn't open() return an error when a pipe open fails? -Because the pipe open takes place in two steps: first Perl calls -fork() to start a new process, then this new process calls exec() to -run the program you really wanted to open. The first step reports -success or failure to your process, so open() can only tell you -whether the fork() succeeded or not. - -To find out if the exec() step succeeded, you have to catch SIGCHLD -and wait() to get the exit status. You should also catch SIGPIPE if -you're writing to the child--you may not have found out the exec() -failed by the time you write. This is documented in L. - -In some cases, even this won't work. If the second argument to a -piped open() contains shell metacharacters, perl fork()s, then exec()s -a shell to decode the metacharacters and eventually run the desired -program. Now when you call wait(), you only learn whether or not the -I could be successfully started...it's best to avoid shell -metacharacters. - -On systems that follow the spawn() paradigm, open() I do what -you expect--unless perl uses a shell to start your command. In this -case the fork()/exec() description still applies. +If the second argument to a piped C contains shell +metacharacters, perl fork()s, then exec()s a shell to decode the +metacharacters and eventually run the desired program. If the program +couldn't be run, it's the shell that gets the message, not Perl. All +your Perl program can find out is whether the shell itself could be +successfully started. You can still capture the shell's STDERR and +check it for error messages. See L<"How can I capture STDERR from an +external command?"> elsewhere in this document, or use the +L module. + +If there are no shell metacharacters in the argument of C, Perl +runs the command directly, without using the shell, and can correctly +report whether the command started. =head2 What's wrong with using backticks in a void context? Strictly speaking, nothing. Stylistically speaking, it's not a good -way to write maintainable code because backticks have a (potentially -humongous) return value, and you're ignoring it. It's may also not be very -efficient, because you have to read in all the lines of output, allocate -memory for them, and then throw it away. Too often people are lulled -to writing: +way to write maintainable code. Perl has several operators for +running external commands. Backticks are one; they collect the output +from the command for use in your program. The C function is +another; it doesn't do this. - `cp file file.bak`; - -And now they think "Hey, I'll just always use backticks to run programs." -Bad idea: backticks are for capturing a program's output; the system() -function is for running programs. +Writing backticks in your program sends a clear message to the readers +of your code that you wanted to collect the output of the command. +Why send a clear message that isn't true? Consider this line: `cat /etc/termcap`; -You haven't assigned the output anywhere, so it just wastes memory -(for a little while). You forgot to check C<$?> to see whether -the program even ran correctly, too. Even if you wrote +You forgot to check C<$?> to see whether the program even ran +correctly. Even if you wrote print `cat /etc/termcap`;