Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Ways and means of killing Win32 processes

by submersible_toaster (Chaplain)
on Feb 03, 2003 at 03:02 UTC ( #232118=perlquestion: print w/ replies, xml ) Need Help??
submersible_toaster has asked for the wisdom of the Perl Monks concerning the following question:

Mellow Funks (sic)

Recently I have been writing perl wrappers around various windows executables, being launched by smedge2 . Being sensible and considerate, (covering my ass) I inserted signal handlers in the wrappers, which call a cleanup sub, whose goal is to kill the PID returned by a piped open. Hence the wrapper cleans up it's own mess. Great! except for the non-POSIX ness of windows. Smedge seems pretty wise to 'processes that refuse to die' and it's method of killing the wrapper does not send any signals that I can catch AFAIK. The by product of course is that the wrapper goes down and it's children go rogue - no caring that nothing is listening to the output pipe.

Win32::Process looks great for managing process, but not for determining whether THIS process is being killed by some OTHER process.

How can I trap this not-a-SIGnal so my wrappers can cleanup correctly?

I can't believe it's not psellchecked

Comment on Ways and means of killing Win32 processes
Re: Ways and means of killing Win32 processes
by fokat (Deacon) on Feb 03, 2003 at 03:35 UTC

    I would begin with making sure you can kill() under Win32, which IIRC you cannot. If my memory is wrong and you can, then do it otherwise. Have your wrappers send a (handled) signal to your program. If your program is there to trap the signal, no error will be reported. If your program has been misteriously terminated, then the call to kill() will fail. Then the wrapper can commit suicide in a graceful manner.

    You can also use a PIPE or socket to maintain some form of IPC with the wrappers, but this approach has more overhead. In any case, you should tune the mechanism in order to tradeoff the time it takes for wrappers to notice the parent is dead vs the resources that would be wasted by this polling.

    Hope this helps.

    Best regards

    -lem, but some call me fokat

      A few clarifications

      NORMALLY: Smedge2 --executes--> Render.exe MY-WRAPPED VERSION: Smedge2 --executes--> --executes--> Render.exe

      The problem being that when smedge2 decides that it should abort a job, it kills the process it executed, this would be fine if there was only one process (NORMALLY) , but MY-WRAPPED has smedge executing the wrapper, sadly when smedge kills '', the children of '' do not die. Moreover, no amount of signal trapping will catch the kill issued by smedge. Indeed it seems very similar to the Taskmanager->EndProcess.

      Now the code, some of which is show below , does work when given a SIGINT from the commandline - ie
      C:\wrappers\ -some args * - output etc * ^C In cleanup.
      And so the child process is killed.
      I can't believe it's not psellchecked

        I did think that you might be able to get around this problem by forking the wrapper process into two and then have the parent process exec the wrapped executable. The thought was that the exec'd executable would run under the original process id, and the child process would know that id and so, be able to monitor it. Smedge would kill the parent and leave the child alone to do its clean-up job.

        Unfortunately this doesn't work (under AS anyway). Firstly the exec'd process runs under a new pid not that of the process it replaces. Secondly, the pseudo nature of forked processes under AS, means that when the exec occurs the parent dies, and it takes the child process (thread in reality) with it.

        Reading perlfork I came across this

        exec() Calling exec() within a pseudo-process actually spawns the requested e +xecutable in a separate process and waits for it to complete before e +xiting with the same exit status as that process. This means that the + process ID reported within the running executable will be different +from what the earlier Perl fork() might have returned. Similarly, any + process manipulation functions applied to the ID returned by fork() +will affect the waiting pseudo-process that called exec(), not the re +al process it is waiting for after the exec().

        Which if I have interpreted it correctly, should mean that you could do something like.

        1. Smedge starts
        2. uses system to start a second copy of the script (in another instance of perl) and passes the process ID of the first to it via the command line. The second copy sits and monitor the presence of the first using some mechanism perhaps kill with an arg of 0 (zero) to check of the first is still in existance or $proc = Win32::Process::Open($orig_pid) to get a handle to the original process and $proc->wait(); to wait for it's demise.
        3. The first copy of then execs the wrapped executable and, if the above description is correct, the original process should then sit and wait until the exec'd executable dies or is otherwise terminated. This would be monitored by the second copy.

        Not a 'nice' mechanism, but it might work.

        The reason for my doubt of the veracity of the above statement from perlfork is that I was unable, in a quick test, to verify it. However, I have come to trust the docs and doubt myself in these situations until I have proven (or had proved) otherwise.

        Examine what is said, not who speaks.

        The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://232118]
Approved by data64
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (9)
As of 2014-08-02 06:36 GMT
Find Nodes?
    Voting Booth?

    Who would be the most fun to work for?

    Results (55 votes), past polls