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

Re^2: The bug in DBI package

by elf_firein (Novice)
on Apr 15, 2009 at 08:17 UTC ( #757585=note: print w/replies, xml ) Need Help??

in reply to Re: The bug in DBI package
in thread The bug in DBI package

Yep. Instead of checking the $? or $! I played a trick.This code sinppet inside a function.
my $status = `gzip -cd filename 2>&1`; print "The status is:$status\n"; if (!($status eq '')) { print " ERROR : $file is corrupt. \n"; return 0; }

It works!!! But do you think this is the right way to tackle?

But problem is when I am trying to close a pipe handle. I did somethig like that:

use IO::Pipe; my @command =qw(gzip -cd filename); my $fh = new IO::Pipe; $fh->reader(@command)|| warn "ERROR : Can't read : $!"; while(<$fh>) { #doing some long job here;such as $variable = readline $fh; . . . } undef $fh;#close $fh if ($? != 0) { print "problem in undef or closing:$? with status:$!"; }

I am getting the last print message as error as:problem in undef or closing:-1 with status:no child process". My question is that is it required to check the $? or $! here? If we ignore it will system dump core?

Replies are listed 'Best First'.
Re^3: The bug in DBI package
by ig (Vicar) on Apr 16, 2009 at 01:12 UTC
    It works!!! But do you think this is the right way to tackle?

    I don't think this is a good solution to your problem. While many unix commands produce no output when they run successfully there are other reasons why you may recieve no output on STDOUT. For example, the command may fail with an error message written to STDERR and nothing written to STDOUT.

    The implementation of system() and backticks (``) are system dependent. For example, the implementation on Windows systems is quite different from that on *nix systems. Thus it is difficult to generalize about them.

    On many (most??, all??, I don't know) *nix systems both system() and backticks (``) use the wait functions to wait for the child process to terminate and obtain its exit status. If the child process has been automatically reaped, as will happen on many systems if SIG{CHLD} is set to 'IGNORE' then wait cannot return the exit status of the child process and, therefore, neither can system() or backticks (the latter by way of $?).

    Presuming that your problem occurs because $SIG{CHLD} is set to 'IGNORE' (the other posts in this thread suggest this is the case) then you have a dilemma - you can't easily determine the exit status of child processes without changing $SIG{CHLD} back to 'DEFAULT' but you can't change $SIG{CHLD] back to default without risk of accumulating zombie child processes.

    I would be skeptical of any code that creates child processes without checking that they complete successfully and handling any errors that occur. While it is possible to do so without using wait to obtain their exit status (e.g. some other IPC signaling mechanism may be used to reliably determine relevant status) doing so is not trivial and I wouldn't trust that it was being done without some evidence. Therefore, I would first investigate to determine what is setting $SIG{CHLD] to 'IGNORE' and rectify any deficiencies there.

    If you can't determine or "fix" the code that is setting $SIG{CHLD} to 'IGNORE' but you want to spawn other processes and obtain their exit status you have several choices:

    You could simply set $SIG{CHLD} to 'DEFAULT' and risk zombie processes accumulating until your program terminates. If only a few child processes are created, this may be fine.

    Alternatively, you could temporarily set $SIG{CHLD} back to 'DEFAULT' only when needed and reap any zombies that accumulated after restoring $SIG{CHLD} to 'IGNORE'. For example:

    use POSIX ":sys_wait_h"; # do whatever that sets $SIG{CHLD} to 'IGNORE' { local $SIG{CHLD} = 'DEFAULT'; # do something interesting here, for example... my $return = system("gzip somefile"); if($return != 0) { # handle exception here } } # reap any zombies that accumulated while # $SIG{CHLD} was set to 'DEFAULT' while ( (my $pid = waitpid(-1, WNOHANG)) > 0 ) { print "reaped $pid with status $?\n"; }

    In passing, it is easy to see how $SIG{CHLD} is set:

    use Data::Dumper; print Dumper(\%SIG); $SIG{CHLD} = 'IGNORE'; print Dumper(\%SIG);
    My question is that is it required to check the $? or $! here? If we ignore it will system dump core?

    I would check exit status after running a system command via system or backticks. For the former I would use the return value (though I believe $? provides the same value) and for backticks I would use $?. If system returns -1 I might check $! because system says:

    Return value of -1 indicates a failure to start the program or an error of the wait(2) system call (inspect $! for the reason).

    For backticks I can find no documentation that says $! indicates the reason for failure if $? is -1, so while I might check it I would be skeptical that it was meaningful.

    The system shouldn't dump core just because a system command failed to complete successfully, regardless of whether you check the exit status. But you probably should handle the error if the command you tried to execute failed for some reason, so you should check the exit status.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://757585]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (3)
As of 2018-05-26 06:49 GMT
Find Nodes?
    Voting Booth?