l i n u x - u s e r s - g r o u p - o f - d a v i s
Next Meeting:
July 7: Social gathering
Next Installfest:
Latest News:
Jun. 14: June LUGOD meeting cancelled
Page last updated:
2002 May 14 14:28

The following is an archive of a post made to our 'vox-tech mailing list' by one of its subscribers.

Report this post as spam:

(Enter your email address)
Re: [vox-tech] signal in perl not being caught
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [vox-tech] signal in perl not being caught

On Tue, May 14, 2002 at 10:02:39AM -0700, Peter Jay Salzman wrote:
> what's wrong with this code snippet?

  You are using the perl system function and expecting to be able to 
catch SIGINT.

On Tue, May 14, 2002 at 11:20:40AM -0700, Jeff Newmiller wrote:
> > $SIG{INT} = sub { die("caught sigint.  aborting."); };
> detail: should have newline in die string to avoid cancelling the process
> before the message gets flushed out to the terminal.

  Great idea for printf to stdout, but actually die sends output to 
stderr (which is unbuffered) and as a bonus supplies it's own newline 
character.  If you specify a newline character in the die output you
actually lose the line number information it would normally provide:

die "signal failed\n";
Uncaught exception from user code:
        signal failed

die "signal failed";
Uncaught exception from user code:
        signal failed at ./signal.pl line 17.

> >    system("$program $T > $result_file");

  The reason you don't get the signal is perl blocks it.

from man perlfunc:
#               Because "system" and backticks block "SIGINT" and
#               "SIGQUIT", killing the program they're running
#               doesn't actually interrupt your program.

  According to the documentation then `` should not work either.

  I highly recommend that you check out the perlfunc man page because
it goes on to show how you can use the return code from system to 
detect if the child was killed, dumped core, or exited abnormally.

  Also keep in mind if you have any shell magic characters in the 
string passed to system there may be a copy of bash spawned to 
interpret the characters in addition to the command you wanted,
so unless you do something like:
  system("exec my_command >> result.$foo");
then the return code information will be mangled by bash.

> Perhaps you want to use backticks so you can keep control of the
> terminal?

  Jeff's suggestion works... but only because `` doesn't block SIGINT
correctly, like the man page says it does.  I can see that `` _does_
block SIGINT but only _after_ reading end of file from it's child,
if the child process closes both stdout and stderr then `` behaves
the same as system, in that SIGINT is not catchable in the parent
perl script.

  Without a doubt there is a bug here, either in documentation or
more likely implementation.

So onto an un-asked question:
- How do I abort running some shell command from perl with SIGINT?

something _like_ this... note that run_me appends to an output file
you may or may not want that... handling output from the commands
run can be done a couple of dozen ways.
#! /usr/bin/perl -w

my $loop = 5;

sub run_me($)
  if (!defined($child_id = fork())) {
    die "fork failed\n";
  } elsif ($child_id) {
    waitpid $child_id, 0;
  } else {
    open STDOUT, ">> output";
    close STDIN;
    close STDERR;

    exec $_[0];

$SIG{"INT"} = sub { die "foo bar" };

while ($loop--)
  print STDERR ".";
  run_me("date; sleep 5");


  There is another bug in strace if you try to trace the above perl
script with '-f' it appears that strace gets confused and stops tracing
the living perl script when the bash script child kills itself.  I'm
going to pretend I didn't see this and go back to what I was working on.

  I also have an unfounded aversion to the perl mailing lists
so if anyone would like to be barbecued they can ask if the perl 
bug above is documentation or implementation...
vox-tech mailing list

LUGOD Group on LinkedIn
Sign up for LUGOD event announcements
Your email address:
LUGOD Group on Facebook
'Like' LUGOD on Facebook:

Hosting provided by:
Sunset Systems
Sunset Systems offers preconfigured Linux systems, remote system administration and custom software development.

LUGOD: Linux Users' Group of Davis
PO Box 2082, Davis, CA 95617
Contact Us

LUGOD is a 501(c)7 non-profit organization
based in Davis, California
and serving the Sacramento area.
"Linux" is a trademark of Linus Torvalds.

Sponsored in part by:
Appahost Applications
For a significant contribution towards our projector, and a generous donation to allow us to continue meeting at the Davis Library.