Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Re: The implementation of SIGHUP in Win32 Perl

by BrowserUk (Pope)
on Sep 01, 2013 at 09:32 UTC ( #1051779=note: print w/ replies, xml ) Need Help??


in reply to The implementation of SIGHUP in Win32 Perl

In theory, the process is only terminated if do_raise() returns true; that only happens if there is no signal handler set for sighup.

If there is a signal handler set, it gets called by do_raise(), whence it has as long as it decides to take, and sig_terminate() is never called. There is no sense in adding a Sleep 950; (which is a little under a second not 9.5 seconds) anywhere.

In reality, I can't get a sighup signal handler to ever be invoked even on 5.18. I run vista, and I never see a dialog prompting me; nor is there any delay 10s or otherwise between killing the process and it disappearing; regardless of whether I've installed a signal handler for HUP.

I'm not really sure I understand your motivation for meditating on this; but I think you need to do a lot more reading and experimenting.


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".
In the absence of evidence, opinion is indistinguishable from prejudice.


Comment on Re: The implementation of SIGHUP in Win32 Perl
Select or Download Code
Re^2: The implementation of SIGHUP in Win32 Perl
by klaten (Novice) on Sep 02, 2013 at 00:20 UTC

    You wrote, "I think you need to do a lot more reading and experimenting," and while that is certainly true (and will still be true the day I die) I hope you and others will consider what I write based upon its merit and utility rather than dismiss it due to my lack of standing within the Perl community.

    You also wrote, "I'm not really sure I understand your motivation for meditating on this." Here in Chicago where I live, the authorities run anti-terrorism public service announcements which say "If you see something, say something," about the need for everyone to contribute to the public safety by reporting their suspicions. I noticed what I believe to be serious problems with the SIGHUP implementation in Win32 Perl. I have some suggestions for how to resolve those problems but I lack the talent, experience, and reputation to resolve those issues myself. I've not seen another discussion covering this issue in the same way. I love Perl even though I don't make a dime from it. I'd feel irresponsible if I did not say anything about this. I have to "say something."

    Although I am a new member of PerlMonks, I've lurked here since Dave Roth was a Perl/Win32 "rock star." I know of your reputation as a current "rock star," and am thrilled by your attention. I believe if I can convince you of what I see as a problem, you have the "pull" to help get it resolved. So now you know my motivation.

      I hope you and others will consider what I write based upon its merit and utility rather than dismiss it due to my lack of standing within the Perl community.

      Hm. I spent 1 day waiting for you to reply to my first questions; and 2 days on and off experimenting with code and reading documentation before replying with my best explanation of my findings.

      If I ignore you in future; it won't be because of your lack of standing in the Perl community. (For all I know you could be Larry himself).

      But the attitude....

      I noticed what I believe to be serious problems with the SIGHUP implementation in Win32 Perl.

      My finding are that there is no implementation of SIGHUP on windows. What is there doesn't appear to do anything useful; and it is hard to see what use it would be put to if it did do something useful.

      Injecting a 9.5 second sleep into a signal handling routine is about as absurd an approach to 'fixing' it as I could imagine.

      But hey. What do I know. Good luck with that.


      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".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        I apologize if my responses are too slow for you. As I said earlier, I am not a professional IT person (although I was in the past), in fact, I am a working class stiff, a security guard. I write when I can.

        While you were posting your response to me, I was busy trying to pull together all my thoughts and ideas into one coherent post which I have since submitted. It took me a couple of hours to put that together. That's the best I've got.

        I have a sixteen-hour double-shift as a security guard tomorrow (ironically, the American "Labor Day" holiday) so you won't hear from me for a while. I mean you no disrespect, in fact, as I wrote earlier I respect your opinion and ideas greatly,

        Now, regarding what you wrote in this post you're right of course, there's no implementation of any signals in Windows itself (including SIGINT or SIGBREAK for that matter), I understand that what Perl is processing as a "signal" in Win32 is a construct of the Microsoft C runtime library. But, what *is* generated by Windows and supposedly translated (the translation is what I believe is failing) by Perl calls into the C runtime library is an EVENT (in this case a CTRL_CLOSE_EVENT). I understand that this event is generated by a Windows Console Object in response to either a user clicking the close button on a console window or the console window receiving a WM_CLOSE message. MSDN describes it like this: "A signal that the system sends to all processes attached to a console when the user closes the console (either by clicking Close on the console window's window menu, or by clicking the End Task button command from Task Manager)."

        Regarding its utility, unless that implementation works, I can see no way that pure Perl would be able to ever trap something as simple as a user accidentally closing a console window running a Perl program with an open data file, or being able to gracefully shutdown if for example an Uninterruptible Power Supply (UPS) sent a power lost, please shutdown the OS message which prompted a system shutdown. Other languages can gracefully deal with these types of situations, and so should Perl.

        I did (independently) reach the same conclusion you did about the 9.5 second thing, a bad idea, but for reasons differently than I imagine you believe.

Re^2: The implementation of SIGHUP in Win32 Perl
by klaten (Novice) on Sep 02, 2013 at 02:59 UTC

    I've had some time to think some more about this issue. Here is additional information.

    IMHO, the key problem with the current implementation is that it seems to assume the console control handler code is being called as a callback (which is what I believe happens in Windows XP), when actually the console control handler code (in Windows Vista and later) is being called from another thread being started by Windows (see note 1, below). This control handler code then triggers Perl's signal handling code, from the other thread. The signal handling code in the Perl program will be running at the same time the Perl program is. I'd be very surprised if Perl were designed to do that!

    In my mind an equivalent scenario would be if I had a Perl program which ran an XSUB that (in C code) started a thread which then tried to call back into the Perl interpreter. Yes, because all the data structures are in the same process, my new thread could access and change things, sure, but due to synchronization and other thread safety issues I'd bet that my new thread would reek havoc upon the Perl interpreter and return results from my thread might be affected by the program still running in the Perl interpreter.

    The other problem is that since Windows Vista, the OS (not Perl) will terminate the process upon the return from the console control handler—regardless of the return value (see note 2, below, and from what I've read elsewhere, this process will eventually be terminated by the OS even if the control handler never returns, see note 3, below). This could abort any type of recovery a Perl signal handler might attempt.

    Here's what I propose as a possible solution. There is code in win32.c to convert a WM_USER_KILL message into a C runtime signal. Instead of having the console control handler code call back into Perl, have it post (or maybe in the case of SIGHUP, send -- so the thread could wait for a response) a message to the main thread of the console (possibly get the the console window handle via a GetWindowConsole-type function?). This would allow the existing code in win32c to recreate a SIGHUP (and also SIGINT and SIGBREAK, because they too would be affected by the threading issue) signal in the main thread, the thread running the Perl interpreter. Although slightly less efficient on Windows XP, this technique should operate on any Windows OS. Another advantage of this technique is that it would allow the use of a message spy type utility to determine whether or not the signal-simulation messages were actually reaching the console window.

    Regarding the process termination issue, I'm less certain. Originally I suggested a rather simplistic "sleep" type solution prior to returning from the console control handler, but I have to admit, that idea stinks. I read here that the timeout on Windows 7 is 10 seconds, but what about Windows Vista? Windows 8? Windows 9, 10, 11? I don't know. Maybe the answer is: just go ahead and let the OS kill the process at that point. I do believe that somehow, the console control handler should be kept from returning until the Perl $SIG handler has a chance to run. How could that happen? Could the idea about the SendMessage for the SIGHUP work? You know better than I on that.

    Anyway, here are my reference notes on this topic:

    1. From msdn: "When the signal is received, the system creates a new thread in the process to execute the function."
    2. From msdn: "The CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT signals give the process an opportunity to clean up before termination. A HandlerRoutine can perform any necessary cleanup, then take one of the following actions:
      • Call the ExitProcess function to terminate the process
      • Return FALSE. If none of the registered handler functions returns TRUE, the default handler terminates the process.
      • Return TRUE. In this case, no other handler functions are called and the system terminates the process."
    3. From the StackOverflow web site: "It looks like you can no longer ignore close requests on Windows 7. You do get the CTRL_CLOSE_EVENT event though, and from that moment on, you get 10 seconds to do whatever you need to do before it auto-closes."
    4. An interesting side note from msdn regarding the CTRL_LOGOFF_EVENT (a similar note appears in the description of the CTRL_SHUTDOWN_EVENT as well): "Note that this signal is received only by services. Interactive applications are terminated at logoff, so they are not present when the system sends this signal."
      The other problem is that since Windows Vista, the OS (not Perl) will terminate the process upon the return from the console control handleróregardless of the return value (see note 2, below, and from what I've read elsewhere, this process will eventually be terminated by the OS even if the control handler never returns, see note 3, below). This could abort any type of recovery a Perl signal handler might attempt.

      I think you've answered your own inquiry. There is nothing the perl process can do about being forcibly terminated.

      And I sincerely doubt there is any merit in trying.

      Windows doesn't do sighup; nor have I felt any need for it. As a Windows user, I know that forcing a program to terminate this way is likely to leave things in an incomplete state; and I use the option as a last resort with that in mind.


      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".
      In the absence of evidence, opinion is indistinguishable from prejudice.
      IMHO, the key problem with the current implementation is that it seems to assume the console control handler code is being called as a callback (which is what I believe happens in Windows XP), when actually the console control handler code (in Windows Vista and later) is being called from another thread being started by Windows (see note 1, below). This control handler code then triggers Perl's signal handling code, from the other thread. The signal handling code in the Perl program will be running at the same time the Perl program is. I'd be very surprised if Perl were designed to do that!


      It is always executed in a separate thread in every NT OS, not just Vista. DOS Win I can't speak about, but it might have actually interrupted the main thread since in old MSDN docs for the CRT, on DOS Win ONLT, there a quite a number of more CRT signals that are catchable than on MS CRT on NT. The multi-threading of the console event dispatch often can cause assert fails and crashes from Perl if Perl is in a 100% CPU usage loop on a multi core machine. I've filed tickets about it in Perl RT. Signals block all other execution I think on Unix. The console event thing runs in a separate thread without stopping the first thread. The runloop in the main thread will get a NULL and exit quickly if the console event thread hasn't gotten to the exit() yet in most cases, or the main thread is in blocking IO and its not a problem for the child thread to reenter the same interp and do perl global destruction.

      My idea for the fix would be to do a SetThreadContext (C debugger-ish stuff) see http://msdn.microsoft.com/en-us/library/windows/desktop/ms680632%28v=vs.85%29.aspx, and try to implement it unix style with the event interrupting execution and executing in the context of the parent thread. NT does have its own implementation of Unix signals called asynchronous procedure calls (APCs) see http://msdn.microsoft.com/en-us/library/windows/desktop/ms681951%28v=vs.85%29.aspx, but if you read about them, they only run when you, the process, requests to rundown the APC queue, so they are always predictable unlike Unix signals (an intentional design), but most syscalls typical Win32 processes are never the "alertable" kind, and if you have a single DLL that you didn't write yourself in the process, you are probably screwed cuz that DLL will be making non-alertable syscalls. If someone really wanted to (space elevator fantasy here), they could DLL hook kernel32, or SSDT hook it, and add APC dispatching to syscalls that dont run APCs. The syscalls would have to be retried by the layer/shim when they fail because APCs ran. The kernel32 and ntdll alertable syscalls dont do that for you.
        It is always executed in a separate thread in every NT OS, not just Vista.

        Ah, that's good to know, thanks.

        The multi-threading of the console event dispatch often can cause assert fails and crashes from Perl if Perl is in a 100% CPU usage loop on a multi core machine.

        That makes sense. So basically we were all just lucky that the other two event triggered signals, SIGINT and SIGBREAK worked. Which validated the advice "don't do too much in your signal handler," because the more you did (or the busier your machine), the more likely you would be to run into a thread conflict causing a crash.

        I looked at the thread context and APC stuff, but both those topics are over my head, I'm afraid. All I was thinking about was to simply "re-throw" the event signals (by "posting" a WM_USER_KILL message from the message handling thread appropriate for the signal to "handle") instead of calling back into Perl. What I wonder about, and perhaps you can help with is this side of the win32.c signal code:

        case WM_USER_KILL: { /* We use WM_USER_KILL to fake kill() with other signals */ int sig = (int)wParam; if (do_raise(aTHX_ sig)) sig_terminate(aTHX_ sig); return 1; }

        Do you know of any issues with that side of the code? I was thinking it would trigger the $SIG{ 'HUP' } in the same thread as the perl interpreter. If that's true, then what I wanted to do might have a chance of working. Anyway, thanks for the feedback.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1051779]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (8)
As of 2014-12-22 15:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (121 votes), past polls