Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Re: System call + signals = bad return code?

by bruceb3 (Pilgrim)
on Sep 28, 2007 at 23:11 UTC ( #641637=note: print w/replies, xml ) Need Help??

in reply to System call + signals = bad return code?

This is a very interesting situation. I have coded up the system call into fork/exec solution and ensured that the signal handler and alarm call are only happening within the parent. Even with this the child is still exiting with -1.
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; print "".localtime(),"\n"; my $pid = fork; die "fork failed\n" if !defined $pid; if ($pid == 0) { # child print "child is $$\n"; exec "/bin/sleep", "4"; die "exec failed:$!\n"; } else { # parent # there is no code in the parent to kill the child if the alarm is + called $SIG{ALRM} = sub { print( "Alarm triggered, making system call in $$\n" ); unlink('/doesnt/exist'); # this will definitely fail }; alarm(2); my $pid = wait; my $status = $?; print "return value from child is $pid and status was $status\n"; } print "".localtime(),"\n";
The output of this code is-
Sat Sep 29 09:04:00 2007 child is 26171 Alarm triggered, making system call in 26170 return value from child is -1 and status was -1 Sat Sep 29 09:04:02 2007

It seems that the failed unlink is causing the return code from the child to be trashed too. This is just speculation, of course. In the perldocs there is talk of problems with signals and different versions of OS being a contributing factor, so I coded up the original code in C;

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <unistd.h> void alarm_sig(int sig) { int rt; puts("in alarm_sig"); if ((rt = unlink("/doesnt/exist")) == -1) { perror("unlink failed"); } } int main() { int rt; signal(SIGALRM, alarm_sig); alarm(2); rt = system("sleep 4"); printf("return value from system %d\n", rt); }

The output of this is -

in alarm_sig unlink failed: No such file or directory return value from system 0

So it doesn't look like it's a problem with my operating system. Need to have a look at this further, later on.

Replies are listed 'Best First'.
Re^2: System call + signals = bad return code?
by bruceb3 (Pilgrim) on Sep 29, 2007 at 02:51 UTC
    So, working on my theory that $? and $! are being trashed because of the call to the signal handler, I localised the variables $? and $! which has made a positive difference. Here is the code.
    $SIG{ALRM} = sub { local $? = 0; local $! = 0; print( "Alarm triggered in $$\n" ); unlink('/doesnt/exist'); # this will definitely fail }; alarm(2); my $rt = system("sleep 4"); print "system returned $rt, \$? is $?\n";

    And the output is -

    Alarm triggered in 26346 system returned 0, $? is 0

    Give it a try in your code. Let me know how is goes.

      Doing anything complicated in a signal handler is scary dangerous. The most common problem lies in memory management -- if your code attempts to malloc() a buffer when the main code is already in malloc(), your heap can get corrupted. It won't happen all the time, and it may not even happen often, but it can happen and it's very hard to debug.

      The Signals section in Chapter 16 (IPC) of the Camel explains the rationale for this further -- but the general rule of thumb is that your handler shouldn't do anything more complicated than updating a variable, e.g.

      my $interrupted = 0; $SIG{ALRM} = sub { $interrupted = 1; };

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2023-01-30 17:05 GMT
Find Nodes?
    Voting Booth?

    No recent polls found