Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: When starting a process, at what point does "open()" return?

by MarkM (Curate)
on Aug 18, 2003 at 05:41 UTC ( #284486=note: print w/ replies, xml ) Need Help??


in reply to When starting a process, at what point does "open()" return?

On UNIX systems, open("...|") works similar to the C function popen(). It returns after calling fork(). There is no guarantee that the process can actually be loaded.

On WIN32 systems, open("...|") creates a new process using CreateProcess(). CreateProcess() will fail immediately if the process cannot be initiated, therefore open() will fail as well. Portable code should not rely on this behaviour.

UPDATE: Perl does have some magic implemented for most UNIX platforms that attempts to pass the error code from child process to parent before open() returns. This should catch most cases involving permissions or the executable not existing.


Comment on Re: When starting a process, at what point does "open()" return?
Re: Re: When starting a process, at what point does "open()" return?
by esh (Pilgrim) on Aug 18, 2003 at 06:03 UTC

    On UNIX systems, open("...|") ... returns after calling fork().

    If this is true, how does open return an error if the program is not found, not executable, or has a bad shabang spec?

    perl -e 'open F, "nosuchprogram |" or die "open: $!\n"; print "don +e\n";'
    outputs:
    open: No such file or directory

    I had assumed that this was because it was only returning after the exec() but I'll admit this seems to take a bit more inter-process communication.

    -- Eric Hammond

      I did some extra checking for you. I hate unexplained behaviour as well... :-)

      With open("program |") Perl opens two pipes on systems that provide fork() (UNIX). The first pipe is for capturing STDOUT, and remains open after execve(). The second pipe is for passing an errno value from the new child to the parent, and is automatically closed as part of execve(). If execve() fails, the value of errno is written in native binary format over the second pipe. The caller monitors this second pipe, and waits until the second pipe closes before it succeeds.

      I wasn't able to quickly determine when this code was introduced into Perl. It does make things convenient. :-)

      Cheers,
      mark

        system(), backticks and pipe open now reflect exec failure
        On Unix and similar platforms, system(), qx() and open(FOO, ``cmd |'') etc., are implemented via fork() and exec(). When the underlying exec() fails, earlier versions did not report the error properly, since the exec() happened to be in a different process. The child process now communicates with the parent about the error in launching the external command, which allows these constructs to return with their usual error value and set $!.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://284486]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (12)
As of 2014-08-27 21:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (253 votes), past polls