in reply to Re^9: Print inside SIGNALS
in thread Print inside SIGNALS

Don't kill the program (e.g. by sending SIGINT to the program) and then complain that the rest of the program (e.g. the signal handler) doesn't run.

I didn't.

$ perl -e 'sleep 10;print"World\n"' | perl -e '$x=time; $SIG{ALRM}=sub{print"Hello ";$y=time}; alarm 2; $z=<>; print $z,$y-$x," ",time-$x,"\n"' Hello World 2 10

On my system, all of the above output does not happen until after 10 seconds. See above.

Replies are listed 'Best First'.
Re^11: Print inside SIGNALS
by Veltro (Hermit) on Jul 19, 2018 at 11:05 UTC

    Funny discussion. But I think both of you are correct.

    When blocking the program with <>, is the alarm signal block executed when I send SIGINT? On Unix/Linux: In case waited long enough for the alarm timeout to happen: Yes, always.

    So why is it not printed? A buffering issue? Yes and no.

    Yes and no?

    Yes, data may be stuck in the buffer when using STDOUT (e.g. it did not have a "\n" when that was the flush condition). But that is not the reason why it is not printed.

    Sigh..., so why is it not printed then?

    Because the program received a SIGINT and terminated because the program does not have a handler. Remind that the intention of SIGINT is to provide a mechanism for an orderly, graceful shutdown. But the program doesn't have that so it has ended prematurely and the buffer is not flushed at normal program end.

    But why is the line ending with a '\n' printed then after sending the SIGINT? Because the line was already transferred to the operating system buffer. But that buffer was only flushed after the blocking <> was terminated.

    This is how I think it works and why I think you are both right. However not entirely explained correctly maybe.

      Sorry, but no, the central point of this discussion has nothing to do with SIGINT, and even whether something is output to STDOUT is a secondary issue. Above, ikegami said that the SIGALRM handler would fire after and not during <>, which I doubted, tested, and showed that it's not how it behaves - at least on my system, in case that makes a difference, hence my oneliners and questions above. The claim that I must've sent the SIGINT before the SIGALRM handler could fire is nonsense.

        I don't care much about what ikagami said exactly, but you did kill the program is what he noticed, and that is what I focus on. As far as I'm concerned that is the reason why your example does not print anything. Maybe a piece of code will help:

        use strict ; use warnings ; alarm 2 ; $SIG{'ALRM'} = sub{ print "Timeout reached" } ; $SIG{'INT'} = sub { exit(0) } ; <> ; __END__ [/tmp] # perl pltst1.pl ^C[/tmp] # perl pltst1.pl ^CTimeout reached[/tmp] # (1. ctrl-c pressed < 2 seconds 2. ctrl-c pressed > 2 seconds)

        1. So you see, it does matter if you kill the program. 2. Whether something is being outputted to STDOUT is not a secondary issue. It matters everything. STDERR and STDOUT buffer mechanisms are fundamentaly different.

        edit: So if people are down-voting this that is fine, but then at least show me where I am wrong please.

        edit 2: Examples added regards the difference between STDOUT and STDERR below (Pevious example was Linux, this was on Windows):

        WITH syswrite STDERR and print STDERR:

        use strict ; use warnings ; alarm 2 ; $SIG{ALRM} = sub{ syswrite STDERR, "s Timeout reached " ; print STDERR "p Timeout reached " ; } ; sleep(4) ; syswrite STDERR, "s Program end " ; print STDERR "p Program end " ; sleep(2) ; __END__ C:\perlproject>perl sigtst.pl s Timeout reached p Timeout reached s Program end p Program end s Timeout reached - Printed after 2 seconds p Timeout reached - Printed after 2 seconds s Program end - Printed after 4 seconds p Program end - Printed after 4 seconds

        WITH syswrite STDOUT and print STDOUT:

        use strict ; use warnings ; alarm 2 ; $SIG{ALRM} = sub{ syswrite STDOUT, "s Timeout reached " ; print STDOUT "p Timeout reached " ; } ; sleep(4) ; syswrite STDOUT, "s Program end " ; print STDOUT "p Program end " ; sleep(2) ; __END__ C:\perlproject>perl sigtst.pl s Timeout reached s Program end p Timeout reached p Program end s Timeout reached - Printed after 2 seconds s Program end - Printed after 4 seconds p Timeout reached - Printed after 6 seconds p Program end - Printed after 6 seconds

      Yes, data may be stuck in the buffer when using STDOUT

      No, not in the <> case. The signal handler is only called between Perl ops, so it can't be called until <> returns, so it hadn't been called by the the time the process was killed. Adding \n wouldn't make a difference.

        Sigh... I said I was done, but this really is bothering me. Sorry for my flurry of replies just now.

        The signal handler is only called between Perl ops, so it can't be called until <> returns

        All I'm asking is if you could please grab a Linux box and run this yourself:

        $ perl -wMstrict -le '$a=time;$SIG{ALRM}=sub{$b=time};alarm 2;<>;print + $b-$a'

        I've tried it lots of times, and no matter how long I wait (Update: as long as it's >2s) to input something (or nothing) and hit enter, the output is invariably 2. The only conclusion I can draw anymore is that this is because the handler fires during <>. I've really done a lot to test this myself - run this under strace, tried lots of different variations of the above onliner, etc.

        All the evidence I've gathered, some of which I've presented, points to <> being interruptible. You keep insisting it isn't, so please, could you show your evidence (=code)? At this point I'd be relieved to be proven wrong. Please don't leave us hanging here.

        Minor edits to wording.

        Update: Thanks everyone. Next time I'll ask for a reality check sooner, before letting my frustration get the better of me. (I'm waiting for the vote fairy.)

Re^11: Print inside SIGNALS
by ikegami (Patriarch) on Jul 20, 2018 at 18:43 UTC

    I didn't.

    Don't lie. Your own output showed you used Ctrl-C.

    all of the above output does not happen until after 10 seconds

    This was already explained.

      Don't lie. Your own output showed you used Ctrl-C.

      You said that I shouldn't complain that the signal handler didn't run, and I said "I didn't", because as far as I could tell the signal handler did run. Update: Improved wording. Also, please see my reply here.