PerlOnTheWay has asked for the wisdom of the Perl Monks concerning the following question:

My program is calling system repeatedly in a loop.

while(1){ system("echo 111"); }

When I press ctrl-c, it doesn't get killed as system seems to be ignoring SIG INT.

Is there a way to make system not ignore SIG INT in Perl?

Replies are listed 'Best First'.
Re: How to make `system` not ignore SIG INT in Perl?
by ikegami (Patriarch) on Sep 13, 2011 at 05:49 UTC

    Seems to me that ^C works quite fine when system is in progress:

    $ perl -MTime::HiRes=time -E' for (;;) { my $s=time; system("sleep", "1"); say time-$s; } ' 1.0089168548584 1.00794720649719 1.00801014900208 ^C0.0198760032653809 ^C0.180072069168091 ^C0.147971153259277 ...

    SIGINT is indeed being sent and received, and a process does indeed die as a result.

    Perhaps you want to check the result returned by system and avoid looping if the child returned an error or died from a signal?

      I provided a minified example in my post,

      does ^C work in that case?

        I don't know how I could tell whether it worked or not using that example, but I have no reason to believe echo isn't receiving the signal or ignores it.
Re: How to make `system` not ignore SIG INT in Perl?
by JavaFan (Canon) on Sep 13, 2011 at 06:27 UTC
    It's not that the command spawned by system ignores SIGINT. It's the fact that once it terminates, your program immediately spawns another. You'd have to time your ^C so it's send when Perl does something else than waiting for the child process to finish. Or you inspect $?:
    while(1) { system("echo 111"); exit if ($? & 127) == 2; # SIGINT == 2 on my system }

      Try this,seems it's not working for complex case:

      perl -we 'while(1){system("echo " . "1 "x 10000 . "|more");exit if ($? + & 127) == 2;}'

        The added pipe means that there now sits a shell between your program and the child processes. I would assume that the shell does not pass on the exit status of its children.

Re: How to make `system` not ignore SIG INT in Perl?
by salva (Canon) on Sep 13, 2011 at 07:06 UTC
    Most system implementations (probably all) configure the INT signal to be ignored from before forking the child process until it is reaped.

    If you don't want this behavior, you will have to implement your own version of system on top of fork and exec. Use some code search web to look for some Open Source implementation of system and use it as a reference (i.e. system in OpenBSD).