Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Matts (1087)

Matts
  (email not shown publicly)

I work for MessageLabs [messagelabs.com] in Toronto, ON, Canada. I write spam filters, MTA software, high performance network software, string matching algorithms, and other cool stuff mostly in Perl and C.

Journal of Matts (1087)

Monday November 04, 2002
02:35 PM

failed exec

[ #8762 ]

Does anyone know how to return errors to the parent process after you've fork()ed, when your exec() fails?

I'm doing this in the clamd tests:

my $pid = fork();
die "Fork failed" unless defined $pid;
if (!$pid) {
  exec($clamd);
}
...

But if clamd fails to start for some reason, I don't know how to find out reliably. exec() of course will return an error, but I don't know how to propogate that to the parent.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • What do you mean by "exec() fails"? From perldoc -f exec

    It fails and returns false only if the command does not exist *and* it is executed directly instead of via your system's command shell (see below).

    Under what conditions do you expect the call to fail? Unless the docs are wrong, if the program you are trying to execute exists, you will never get a false value from exec. Perhaps system() would be a better choice, and you can handle terminating the child process manually?

    • Sorry I guess I wasn't clear. I mean it fails in exactly the manner described that you quoted ;-)

      i.e. how can I communicate back to the parent this error condition?
      • Non-zero exit code from the child. Your wait call's return value can be used to make sure that you get the expected child's death. You can use a time-out, since "success" probably means that the child never effectively exits (or if it does, the time-out is probably not needed). When wait returns the PID of the deceased child, $? will have the status/exit code.

        --

        --rjray

      • Maybe you can use some variant of the following? We use Windows boxes at work (damn it!), so I rarely get a chance to do much nifty stuff with forking. As a result, I could totally be smoking crack with this.

        #!/usr/bin/perl -w
        use strict;

        #!/usr/bin/perl -w
        use strict;
        use IO::Handle;
        pipe( READER, WRITER );
        WRITER->autoflush(1);

        # Change the following line to a non-existent program to test
        my $program = '/usr/bin/echo';
        my $pid = fork;
        die unless defined $pid;

        unless ($pid) {
           

        • I don't think so, because the line:
          my $line = <READER>;
          would block, so if the exec() worked fine, it would never return. I'll try it though - you never know.

          Plus if you set the pipe to non-blocking reads, then there's timing issues. How long do you wait for something to come out of the pipe?
  • wotcher Matt --

    just exit(1), and make sure the parent calls wait() at some point (or polls with waitpid(WNOHANG)), and checks the exit status.
  • IPC::Run [cpan.org] does it by opening a pipe() to sync to the child, fork()ing, and marking it as close on exit with a fcntl(). Here are some snippets glued together from pieces of IPC::Run:

       ( $sync_reader_fd, $self->{SYNC_WRITER_FD} ) = _pipe ;
       $kid->{PID} = fork() ;
       croak "$! during fork" unless defined $kid->{PID} ;

       unless ( $kid->{PID} ) {
          eval {   
             open $s1, ">&=$self->{SYNC_WR