in reply to How do I cleanly kill a spawned process on Win32.

Use perl's kill with

  1. a signal value of 2/'INT'

    and perl will call GenerateConsoleCtrlEvent() with CTRL_C_EVENT.

  2. a signal value of 15/'TERM' or 21/'BREAK'

    and perl will call GenerateConsoleCtrlEvent() with CTRL_BREAK_EVENT.

If the receiving process is another Perl script, it can trap these events using the appropriate %SIG handlers.

If is is a non-perl program it will need to use SetConsoleCtrlHandler() to install handlers to respond to the generated events and exit cleanly.


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.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."

Replies are listed 'Best First'.
Re^2: How do I cleanly kill a spawned process on Win32.
by DrWhy (Chaplain) on Feb 26, 2009 at 10:14 UTC
    Ha. That's exactly what I thought I saw from poking through Perl's source code. Is this documented anywhere?

    FWIW, the server I'm testing already has a SetConsoleCtrlHandler defined, which is why I started this whole exercise in the first place.

    --DrWhy

    "If God had meant for us to think for ourselves he would have given us brains. Oh, wait..."

        The kill method does not send signals on windows. See http://perldoc.perl.org/perlport.html. I spent a long time determining how to start a process on windows and then send a ctrl-c "signal". The secret is perl shares the console with the application that was started. Enjoy!
        #!/usr/bin/perl use strict; use warnings; use Win32; use Win32::Process; use Win32::Process 'STILL_ACTIVE'; use Win32::Process::Info qw{NT}; use Win32::Console; my $exe = $ARGV[0]; my $params = $ARGV[1]; my $appWorkingDir = $ARGV[2]; my $signalPollIntervalMillisec = $ARGV[3]; my $signalKillFile = $ARGV[4]; my $signalShutdownFile = $ARGV[5]; # Never die, only when child process terminates $SIG{INT} = 'IGNORE'; $SIG{TERM} = 'IGNORE'; my $ProcessObj; my $success = Win32::Process::Create($ProcessObj,$exe,$params,0,NORMAL +_PRIORITY_CLASS,$appWorkingDir); if ( $success ) { my $pid = $ProcessObj->GetProcessID(); while ( 'true' ) { $ProcessObj->Wait($signalPollIntervalMillisec); $ProcessObj->GetExitCode($exitcode); if ( $exitcode == STILL_ACTIVE ) { # Take action base on some flag if ( -e $signalKillFile ) { kill -9, $pid; exit -3; } elsif ( -e $signalShutdownFile ) { my $CONSOLE = Win32::Console->new(); $CONSOLE->GenerateCtrlEvent(CTRL_C_EVENT); } } else { # Process terminated on it's own exit $exitcode; } } }
Re^2: How do I cleanly kill a spawned process on Win32.
by cdarke (Prior) on Feb 26, 2009 at 09:25 UTC
    The program does not need to call SetConsoleCtrlHandler() if the only concern is shutdown via DllMain. The default action of GenerateConsoleCtrlEvent() is to call ExitProcess() which calls DllMain with DLL_PROCESS_DETACH, however it does not get called with DLL_THREAD_DETACH.

    The idea way would be to have a thread of the server waiting on an Event, then fire the Event when closedown is needed.
      The program does not need to call SetConsoleCtrlHandler() if the only concern is shutdown via DllMain.

      If you are going to allow the default handler to call ExitProcess(), then I see no advantage over calling TerminateProcess(). You wouldn't even be able to choose what exit value is returned.

      If the OP is hoping to be able to perform some kind of clean up and controlled shutdown, he would need to install his own handler.

      The idea way would be to have a thread of the server waiting on an Event, then fire the Event when closedown is needed.

      You'd have to expand on that a little. What would be the advantage in having a separate thread?

      SetConsoleCtrlHandler() can already handle all of these events:

      1. CTRL_C_EVENT:
      2. CTRL_CLOSE_EVENT:
      3. CTRL_BREAK_EVENT:
      4. CTRL_LOGOFF_EVENT:
      5. CTRL_SHUTDOWN_EVENT:

      Are you suggesting that the OP should spawn a separate thread that installs handlers and then goes to sleep waiting for them to occur? If so, how would you suggest that it then "interupt" the main thread when they do?

      Or are you suggesting creating some kind of user event that this extra thread would wait on? If so, how would the Perl script generate that event? And what would the extra thread do with it when it arrived?


      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 agree that, all things considered, an Event will be the most appropriate way to handle this.

      In my experience, “murder is always messy.”   :-D   More to the point, “it's never exactly the same way twice.” So, it's very difficult to test.

      You might have one thread in the application that does nothing but wait for the closing whistle. It starts-up the app, waits for the whistle, quickly notifies the workers, waits briefly for them to respond, and then closes down the app as neatly as it can manage.