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

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.

Replies are listed 'Best First'.
Re^13: Print inside SIGNALS (updated)
by haukex (Archbishop) on Jul 20, 2018 at 19:25 UTC

    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

        Thank you very much for your reply! Your test results are consistent with mine. I was worried at one point that maybe my Linux box or build of Perl might be behaving differently from others', but now I've gotten some confidence back that my tests were probably ok.

      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

        Thank you very much for your reply! I had a chance to test on Windows earlier today, and also just tested all your examples as well, Windows and Linux. It really does seem that <> doesn't appear to be interruptible by signal handlers there, even if I forcibly close STDIN (this works to abort <> on Linux). pedrete said in the root node "Linux Debian", which is why I had left Windows out of my considerations (and didn't even test there initially) and only talked about Linux.

      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.

        Thank you very much for your reply! As I replied to pryrt, I also now see the different behavior on Windows.

        During all my earlier testing I was actually reminded of an interaction between sleep and alarm: "You probably cannot mix alarm and sleep calls, because sleep is often implemented using alarm." Note how the second and third times are the same:

        $ perl -wMstrict -e '$SIG{ALRM}=sub{print time." Timeout"};print time. +" Before\n";alarm 2;sleep 10;print time." After\n"' 1532118865 Before 1532118867 Timeout1532118867 After

        But if you emulate sleep with polling, you see the same buffering issue as in the other cases - here, the second line of output isn't printed until after the 10 seconds are up:

        $ perl -wMstrict -e '$SIG{ALRM}=sub{print time." Timeout"};print time. +" Before\n";alarm 2;$a=time+10;1 while time<$a;print time." After\n"' 1532118963 Before 1532118965 Timeout1532118973 After

        Update: And on Windows:

        > perl -wMstrict -e "$SIG{ALRM}=sub{print time.qq{ Timeout}};print tim +e.qq{ Before\n};alarm 2;sleep 10;print time.qq{ After\n}" 1532119202 Before 1532119204 Timeout1532119212 After > perl -wMstrict -e "$SIG{ALRM}=sub{print time.qq{ Timeout}};print tim +e.qq{ Before\n};alarm 2;$a=time+10;1 while time<$a;print time.qq{ Aft +er\n}" 1532119272 Before 1532119274 Timeout1532119282 After

        Where each second line of output isn't printed until after 10 seconds.