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

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.

Replies are listed 'Best First'.
Re^12: Print inside SIGNALS
by haukex (Archbishop) on Jul 19, 2018 at 17:34 UTC

    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
        I don't care much about what ikagami said exactly

        That's a strange thing to say when that's all this sub-thread is about. Please re-read the thread starting from here.

        ctrl-c pressed < 2 seconds

        No, that's exactly the thing I have an issue with: I certainly have a dense moment now and then, but I'm not dumb enough to set an alarm for two seconds upon which something is to be printed, kill the program before the two seconds is up, and then use this as my evidence that nothing was printed. And I'm going to take special care when I'm pointing out a potential mistake to a Monk whose technical knowledge is much deeper than mine and who is almost always right in his posts.

        And it should be obvious to anyone that I didn't hit Ctrl-C within the first two seconds if they had actually run my first two one-liners (again, assuming their system behaves the same as mine). Which is why I posted them in the first place!

        but you did kill the program ... As far as I'm concerned that is the reason why your example does not print anything.

        Then you are making this same incorrect (and insulting) assumption that ikegami did. Did you try out my most recent one-liner that has nothing to do with SIGINT?

        STDOUT ... matters everything

        No, it does not.

        $ perl -e '$x=time; $SIG{ALRM}=sub{$y=time; close STDIN}; alarm 2; <>; print STDERR $y-$x," ",time-$x,"\n"' 2 2

        Just to make it clear: This shows how <> is interrupted by $SIG{ALRM}, without STDOUT being involved at all. Which is why I think that the first snippet posted by pedrete here is just suffering from buffering (but I'm always willing to be proven wrong).

        $SIG{'INT'} = sub { exit(0) } ;

        This misses the point, because of course the output buffers get flushed on exit. With buffering issues, the question is not whether something gets printed, but when. And perhaps you overlooked that the OP confirmed that it was a buffering issue all along.

        I've said all I can say until someone shows some actual evidence to the contrary.

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

    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.)

        G'day haukex,

        Following your CB request, I ran this a few times for you. Firstly, here's what I'm using:

        $ uname -a Linux ibm-laptop.diversityarrays.com 4.1.34-33-default #1 SMP PREEMPT +Thu Oct 20 08:03:29 UTC 2016 (fe18aba) x86_64 x86_64 x86_64 GNU/Linux $ perl -v | head -2 | tail -1 This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-li +nux-thread-multi
        "I've tried it lots of times, and no matter how long I wait to input something (or nothing) and hit enter, the output is invariably 2.

        I got different results: ran it four different ways; only got 2 once.

        I wrapped your one-liner in date commands to indicate the wait time; however, this didn't work when I issued an interrupt (^C). Here's the runs:

        Hitting Enter almost immediately:

        $ date; perl -wMstrict -le '$a=time;$SIG{ALRM}=sub{$b=time};alarm 2;<> +;print $b-$a'; date Sat Jul 21 05:55:19 AEST 2018 Use of uninitialized value $b in subtraction (-) at -e line 1, <> line + 1. -1532116519 Sat Jul 21 05:55:20 AEST 2018 $

        Hitting Enter after several seconds:

        $ date; perl -wMstrict -le '$a=time;$SIG{ALRM}=sub{$b=time};alarm 2;<> +;print $b-$a'; date Sat Jul 21 05:56:58 AEST 2018 2 Sat Jul 21 05:57:05 AEST 2018 $

        Hitting Ctrl-C almost immediately:

        $ date; perl -wMstrict -le '$a=time;$SIG{ALRM}=sub{$b=time};alarm 2;<> +;print $b-$a'; date Sat Jul 21 05:59:28 AEST 2018 ^C $

        Hitting Ctrl-C after several seconds:

        $ date; perl -wMstrict -le '$a=time;$SIG{ALRM}=sub{$b=time};alarm 2;<> +;print $b-$a'; date Sat Jul 21 06:00:13 AEST 2018 ^C $

        Finally, please consider this response in isolation. I did start reading this thread when it first appeared; I stopped doing that when umber-hued material appeared to be headed for a cooling device. I followed the link you provided in the CB and replied directly; I didn't review any part of the thread before doing so.

        — Ken

        As a third party: I was debating whether to interject, but this gave me an opening. I have seen what looks like (to me) both behaviors -- I added in some extra information (perl version, timestamp) when prints happen, and ran some one-liners similar to Re^6: Print inside SIGNALS.

        In Windows, I see what I think ikegami has described: no matter what, the SIG{ALRM} isn't firing, presumably because the <> blocks it...

        C:\usr\local\share\PassThru\perl>perl -wMstrict -e "sub p { local $, = + qq{: }; print $], scalar(localtime), @_ }; alarm 2; $SIG{ALRM}=sub{p + qq{Timeout reached\n} }; p qq{before I hit enter\n}; <>; p qq{after +I hit enter\n}" 5.026002: Fri Jul 20 12:20:40 2018: before I hit enter never saw the timeout, so hit enter 5.026002: Fri Jul 20 12:20:57 2018: after I hit enter C:\usr\local\share\PassThru\perl>perl -wMstrict -e "sub p { local $, = + qq{: }; print $], scalar(localtime), @_ }; alarm 2; $SIG{ALRM}=sub{p + qq{Timeout reached } }; p qq{before I hit enter\n}; <>; p qq{after +I hit enter\n}" 5.026002: Fri Jul 20 12:21:05 2018: before I hit enter never saw the timeout, so hit enter 5.026002: Fri Jul 20 12:21:21 2018: after I hit enter

        But in linux, with the \n, the "timeout reached" prints after the 2 seconds, then when I hit ENTER, it prints what comes after the <>; but if I don't have \n, I can count to about 15, type, and hit ENTER, and then it will print both the "timeout reached" and the "after" messages on the same line, showing that the events themselves happened about 30sec apart.

        pryrt@pryrtdebian:~$ perl -wMstrict -e 'sub p { local $, = qq{: }; pri +nt $], scalar(localtime), @_ }; alarm 2; $SIG{ALRM}=sub{p qq{Timeout +reached\n} }; p qq{before I hit enter\n}; <>; p qq{after I hit enter\ +n}' 5.020003: Fri Jul 20 12:23:50 2018: before I hit enter 5.020003: Fri Jul 20 12:23:52 2018: Timeout reached after two seconds, that popped up, then I typed this slowly, with ENTE +R 5.020003: Fri Jul 20 12:24:12 2018: after I hit enter pryrt@pryrtdebian:~$ perl -wMstrict -e 'sub p { local $, = qq{: }; pri +nt $], scalar(localtime), @_ }; alarm 2; $SIG{ALRM}=sub{p qq{Timeout +reached } }; p qq{before I hit enter\n}; <>; p qq{after I hit enter\ +n}' 5.020003: Fri Jul 20 12:24:22 2018: before I hit enter counted to about 15, never saw timeout, typed this, hit ENTER 5.020003: Fri Jul 20 12:24:24 2018: Timeout reached 5.020003: Fri Jul + 20 12:24:57 2018: after I hit enter

        To me, it really looks like under linux, the <> is not blocking the SIG{ALRM} from firing, and that the \n is showing it's buffering which is causing the delay when there's no \n. I cannot explain what I saw, otherwise.

        armed with haukex's newest oneliner, I see

        __WINDOWS__ C:\usr\local\share\PassThru\perl>perl -wMstrict -le "$a=time;$SIG{ALRM +}=sub{$b=time};alarm 2;<>;print $b-$a" Use of uninitialized value $b in subtraction (-) at -e line 1, <> line + 1. -1532115378 __LINUX__ pryrt@pryrtdebian:~$ perl -wMstrict -le '$a=time;$SIG{ALRM}=sub{$b=tim +e};alarm 2;<>;print $b-$a' 2

        once again, I see that on Windows, it appears that <> has prevented the alarm from firing; but in linux, it did not. In windows, I added in a second sleep after the first print, and did the print again:

        __WINDOWS__ C:\usr\local\share\PassThru\perl>perl -wMstrict -le "$a=time;$SIG{ALRM +}=sub{$b=time};alarm 2;<>;print $b-$a;sleep 5; print $b-$a" Use of uninitialized value $b in subtraction (-) at -e line 1, <> line + 1. -1532115756 10

        between the first and second print, after hitting enter for the <>, then there is enough time for the alarm to run. Doing the same in linux, it seems to me that ALARM triggered the once, during the initial time before <> was completed by my hitting enter, so I don't think <> was blocking it:

        __LINUX__ peter@peterjonesdebian:~$ perl -wMstrict -le '$a=time;$SIG{ALRM}=sub{$ +b=time};alarm 2;<>;print $b-$a;sleep 5;print $b-$a' 2 2

        edit: joined lines that were accidentally separated when I copied from windows cmd.exe window

        Hi haukex,

        I have run your program and I keep getting 2 as a result too (on Linux)

        I've tried to create something that also works on Windows:

        alarm 2; $SIG{ALRM} = \&Finish; print "Sleep 5\n" ; sleep 5 ; sub Finish { print "Sleep 5 sig\n" ; sleep 5 ; print "Timeout reached\ +n"; } __END__ Sleep 5 Sleep 5 sig Timeout reached

        You have to actually run this to see that it runs for 10 seconds. This shows that the first sleep is actually suspended and the sleep inside the Finish routine is executed, once if finishes it continues to execute the other previous sleep.

        Yesterday I was testing on Linux and Windows back and forth and I think I got confused somewhere. It is clear to me that Windows behaves very different if it comes down to signals. I know that the OP asked for Linux assistance as well, so my response right now may be off topic I know.