in reply to Re^5: Strawberry Perl and alarm() on Windows
in thread Strawberry Perl and alarm() on Windows
or you don't understand what happens in my code when it runs on Linux. (Did you actually run it on a Linux system?)
No. I don't use Linux. And you're right. I did misinterpret what I saw in your post.
My main purpose was to point out:
See the PERL_ASYNC_CHECK() in run.c and Perl_despatch_signals(pTHX) in mg.c
See also perldoc/perlipc:
Long-running opcodes
As the Perl interpreter only looks at the signal flags when it is about to execute a new opcode, a signal that arrives during a long-running opcode (e.g. a regular expression operation on a very large string) will not be seen until the current opcode completes.
The rest was an attempt to understand (from your posted output) how linux was apparently able to interrupt flock when it appears to be implemented as a single opcode; and thus (according to my understanding of safe signals) should not be interruptible.
I don't understand why that works for you, unless you have PERL_SIGNALS=unsafe?
The (wrong) explanation I came up with seemed to fit; but then it is well passed the end of my (logical) day here and I'm somewhat punchy.
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^7: Strawberry Perl and alarm() on Windows
by afoken (Chancellor) on May 24, 2015 at 19:16 UTC | |
I don't understand why that works for you, unless you have PERL_SIGNALS=unsafe? PERL_SIGNALS is not set in my environment. But PERL_SIGNALS does not affect the operating system in any way. Linux deliveres SIGALRM as it would for any other program. That means that the flock() system call (deep inside the perl flock() function) will be interrupted and will return EINTR immediately after the signal handler (deep inside the perl executable, not $SIG{'ALRM'}) has returned. The signal handler will - according to Deferred Signals (Safe Signals) - just set a flag. So a few CPU cycles after SIGALRM, the flock() system call will return. Standard Unix behaviour. Perl obviously does not attempt to restart the interrupted flock() system call, but makes the perl-level flock() function return false after setting $! to EINTR. Just before the perl-level flock() function returns, perl consideres the situation safe for signals, checks the flag set in the real signal handler, finds it set, and calls the perl-level signal handler stored in $SIG{ALRM}. With unsafe signals, the flock() system call would be interrupted as above, but instead of setting a flag, the signal handler (deep inside the perl executable) would directly invoke the perl-level signal handler stored in $SIG{ALRM}. Everything else would behave the same: If &$SIG{ALRM} returns, control returns to the place where the fcntl() system call was invoked (i.e. the implementation of the fcntl perl function), with fcntl() returning EINTR. That would make the perl function return false after setting $! to EINTR. The only two differences here are: Another demo: This code only warns when a signal was caught, and all of the Win32 workarounds and timing is stripped from the orignal demo. say also writes time and PID.
Output:
The interesting effect of unsafe signals is that flock() in main returns true, there is no warning message. But as you can see from the timing, flock() in main returns only after the helper has released its lock. So in that case, perl must have restarted the interrupted flock() system call. strace confirms that: (Note that strace traces only the main process, not the fork()ed child.)
Unsafe signals seem to change how rt_sigaction is called: SA_RESTART is set only for unsafe signals. So fcntl() is automatically restarted (not by perl, as I wrote above) only with unsafe signals. Another round of strace also confirmes that:
SA_RESTART is only set for unsafe signals. So with unsafe signals, interrupted system calls are restarted if possible; with safe signals, interrupted system calls are not restarted. That is at least strange, perhaps even a bug. I think that perl should either always or never restart interrupted system calls, not depending on safe or unsafe signal handlers. Deferred Signals (Safe Signals) says unter "Restartable system calls":
So, this starts to look like a bug in unsafe signals. SA_RESTART should not be set in Perl 5.8.0 and later, no matter what type of signal handlers is used. <UPDATE> Relevant code is in util.c, functions Sighandler_t Perl_rsignal(pTHX_ int signo, Sighandler_t handler) and int Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save). Both have the following four lines:
</UPDATE> See also: Linux signal handling Alexander
-- Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-) | [reply] [d/l] [select] |
by BrowserUk (Patriarch) on May 24, 2015 at 19:27 UTC | |
But PERL_SIGNALS does not affect the operating system in any way. Linux deliveres SIGALRM as it would for any other program. That means that the flock() system call (deep inside the perl flock() function) will be interrupted and will return EINTR immediately after the signal handler (deep inside the perl executable, not $SIG{'ALRM'}) has returned. Sorry, but I think you're wrong. The signal is "delivered" to the process, but the process can block, or ignore it or (as perl since 5.8.1) defer it. The mechanism for doing this is sigprocmask(2) and the code that does it is for perl in Perl_despatch_signals() in mg.c. But, this is way outside my knowledge base, so I'll just leave this there. With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
I'm with torvalds on this
In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked
| [reply] |
by afoken (Chancellor) on May 24, 2015 at 20:50 UTC | |
But PERL_SIGNALS does not affect the operating system in any way. Linux deliveres SIGALRM as it would for any other program. That means that the flock() system call (deep inside the perl flock() function) will be interrupted and will return EINTR immediately after the signal handler (deep inside the perl executable, not $SIG{'ALRM'}) has returned. We are talking about a signal that has a custom signal handler set up. Blocking or ignoring is completely irrelevant for this discussion. But yes, the kernel runs through some code that decides if how the signal is handled. Options are: This happens during delivery, before user mode code is called. For some signals (SIGKILL and SIGSTOP), the only option is the default handler. The kernel will enforce that handler, even if you have managed to set up blocking, ignoring, or a signal handler for those signals. What you call "defer" is not a special option for signal handling, but just a user mode signal handler that only sets a flag, combined with code to poll that flag later. This happens completely in user mode, inside the perl executable. But, this is way outside my knowledge base Yes, it seems so. Alexander
-- Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-) | [reply] [d/l] [select] |
by BrowserUk (Patriarch) on May 24, 2015 at 20:57 UTC |