RE: how to kill process on Windows started with os.spawn?

Regarding how to kill a process on Windows which was started with os.spawn*, on the Spambayes list I asked: >> How would I kill that process on Windows, Mark Hammond replied: This worked for me just then: >>> os.spawnl(os.P_NOWAIT, "f:\\windows\\notepad.exe") 548 >>> import win32api >>> win32api.TerminateProcess(548,0) Tim also replied: Tim> For 2.3, I implemented something or other for the Python core; Tim> probably killpid(); Shouldn't one of these solutions (or some variant) appear under the veneer of os.kill()? I realize the semantics might not be exactly the same (perhaps Windows solutions don't support different signals or a different set of signals), but it seems to me that if an attempt is made to provide the os.spawn* functions across platforms we should make a similar attempt to provide a way to kill spawned processes as well. Corollary question: Is there some reason the win32api stuff isn't in the core? Skip

[Skip Montanaro]
I didn't remember correctly -- I implemented waitpid() for Windows. Processes on Windows aren't meant to be externally killed, and the docs have dire warnings about use of TerminateProcess. Not that people don't use it, but it's dangerous.
Shouldn't one of these solutions (or some variant) appear under the veneer of os.kill()?
Signals make little sense on Windows.
I realize the semantics might not be exactly the same (perhaps Windows solutions don't support different signals
Mone -- the second argument to TerminateProcess isn't a signal number, it's the exit code to be returned by the terminated process.
or a different set of signals),
Nope, none.
Be my guest <wink>.
Corollary question: Is there some reason the win32api stuff isn't in the core?
I *expect* Guido would like that, provided the code fit the Python style guide and the docs were bashed into LaTeX. That's a massive amount of no-fun work, and I don't expect Mark to volunteer for either.

The key difference is that kill() wants a PID, while TerminateProcess wants a handle. Now, we *could* add a kill() (assuming it is not already there) but that would not solve your specific problem, as you have a handle and you would then need a platform specific way to convert it to a PID. It seems too hard to win.
Yes, a higher-level execution API would be worthwhile, especially if that could be expressed using posix semantics as a fallback. I am thinking of what threading is to thread, this new API could be to the various spawn/exec/popen functions.
Corollary question: Is there some reason the win32api stuff isn't in the core?
Even if we ignore Tim's requirements ('cos I know I will <wink>) there is still alot of work, and a *huge* amount of code. Do we want win32api, all of the "win32*" modules in win32all, or all of win32all. The win32api modules seems very useful, and it is for trivial things - but once you start doing real things, the other win32 modules start becoming useful, and so it goes. On the other hand, if these extensions were in the core, I wouldn't personally be worrying about those damn hex literal warnings <wink>. Mark.

>> Shouldn't one of these solutions (or some variant) appear under the >> veneer of os.kill()? I realize the semantics might not be exactly >> the same Mark> The key difference is that kill() wants a PID, while Mark> TerminateProcess wants a handle. Posix.kill() wants a pid. Can't os.kill() want anything it wants? ;-) In particular, can't it test its arguments to see if it got a handle or a pid then "Do The Right Thing" (tm Spike Lee I think)? I guess I'm lobbying for os.kill() or something like it (os.retire()?) to be the terminator for os.spawn*, regardless what those functions return. It seems weird to be able to create processes on various platforms but not be able to kill them as well. For the python-dev types not on the spambayes list, I do have an application in mind. In my environment I need to tunnel SB's pop3proxy app through an ssh connection. Starting and stopping it works okay on my MacOSX system, and I presume it will under other Unix-based systems. I began thinking about whether this would port to other platforms and noticed that os.kill() is only supported under Unix. It may turn out that my desire is moot if ssh can't be run under Windows anyway. Skip

[Skip Montanaro]
Posix.kill() wants a pid. Can't os.kill() want anything it wants? ;-)
Yes. On Windows it wants a handle, because that's what spawn*() returns on Windows. But, again, Windows processes aren't intended to be killed externally.
In particular, can't it test its arguments to see if it got a handle or a pid then "Do The Right Thing" (tm Spike Lee I think)?
No, process handles and process ids are both just "little integers" on Windows.
Why do you need to kill a process externally? For example, why can't you make "please stop now" a part of the protocol, so that a process can terminate itself gracefully when told to?
It may turn out that my desire is moot if ssh can't be run under Windows anyway.

Tim Peters <tim.one@comcast.net> writes:
That sounds like FUD. Why is it that processes aren't intended to be killed? Because the assassin can't know what state the process is in, so the process may not complete correctly? This is a general problem with killing, not specific to Windows, and it never stopped a killer. Or can you crash the operating system or the killer process by terminating some other process?
Because the process did not respond to the protocol. Should I kill it anyway and send a bug report to Microsoft? Regards, Martin

[Tim]
[martin@v.loewis.de]
That sounds like FUD.
Argue w/ Microsoft -- you've read their docs.
It's easy to find long articles about the dangers on the net. Here's one I don't think has been posted before: http://tinyurl.com/35o6
It's certainly possible to crash Win9x by killing processes, and easy to hang the killer process (indeed, I have four shareware "process killers" on my home box, as no single one of them is able to kill everything -- sometimes I have a hung process, and three hung process killers trying to nuke it! Win98SE generally becomes too unstable to continue running at that point.).
Because the process did not respond to the protocol. Should I kill it anyway and send a bug report to Microsoft?
The questions were addressed to Skip about his specific app. It sounded to me like he wanted to kill() routinely, instead of pursuing a clean shutdown. The TerminateProcess function is used to unconditionally cause a process to exit. Use it only in extreme circumstances. The state of global data maintained by dynamic-link libraries (DLLs) may be compromised if TerminateProcess is used rather than ExitProcess. because TerminateProcess doesn't notify attached DLLs of process termination -- it's not solely the killed process's state that can get hosed.

Tim Peters <tim.one@comcast.net> writes:
That sounds like FUD.
Argue w/ Microsoft -- you've read their docs.
Apparently not the ones you've read. The documentation of TerminateProcess does not include any warning, except for the recommendation to only use it extreme circumstances, and that the global state maintained by DLLs may be compromised. Please correct me if I'm wrong, but on NT+, there isn't any global state maintained by DLLs that could get corrupted. I interpret the warning as suggesting that "normal" shutdown procedures should be used if possible.
It mentions a number of methods to find the window, then explains that sending WM_CLOSE may fail, to finally explain that TerminateProcess should always work, and that you may lose data by using it. This is exactly the same as on Unix: If you kill a process that was just saving a file, the file may get corrupted. If there were unsaved data, they are lost. This is no reason not to use TerminateProcess.
That sounds like a bug in the killers. TerminateProcess returns immediately, according to the documentation. Now, the process may not terminate if it is blocked in the kernel (the same issue exists on Unix, leading to zombie processes). If the killer then invokes WaitForProcessClose, it is not surprising if it hangs. Your observations suggest "Don't use TerminateProcess on Win9x". I would extend this warning to "Don't use Win9x" :-)
Can you explain what the "global state" of a DLL is? It may have global state on Win9x, and be "attached" to a process - but I understand there is nothing "global" on NT+; the code gets mapped into the process (which gets cleaned up when the process is terminated), and there are no shared data. Regards, Martin

Martin, I'm not interested in arguing about this. If you want to implement os.kill() for Windows, go ahead. I only ask that the docs repeat the vendor's warnings against using it. It's fine for adult use, where "adult" means you know you're courting trouble and are prepared to accept the consequences.

>> In my environment I need to tunnel SB's pop3proxy app through an ssh >> connection. Tim> Why do you need to kill a process externally? For example, why Tim> can't you make "please stop now" a part of the protocol, so that a Tim> process can terminate itself gracefully when told to? I start the background ssh process from within pop3proxy, so it seems to me I ought to be the one to terminate it. As for protocol, I'm not aware of another way to terminate a running ssh other than to call kill(2) with a specified signal. That's more-or-less the Unix way. I don't have the luxury of modifying ssh to understand some application-specific protocol. Skip

[Tim]
[Skip Montanaro]
I start the background ssh process from within pop3proxy, so it seems to me I ought to be the one to terminate it.
OK, that wasn't clear to me before.
No, I'm not asking you to be silly <wink>. The Unix signal model isn't going to fly for you on Windows regardless.

[Skip Montanaro]
I didn't remember correctly -- I implemented waitpid() for Windows. Processes on Windows aren't meant to be externally killed, and the docs have dire warnings about use of TerminateProcess. Not that people don't use it, but it's dangerous.
Shouldn't one of these solutions (or some variant) appear under the veneer of os.kill()?
Signals make little sense on Windows.
I realize the semantics might not be exactly the same (perhaps Windows solutions don't support different signals
Mone -- the second argument to TerminateProcess isn't a signal number, it's the exit code to be returned by the terminated process.
or a different set of signals),
Nope, none.
Be my guest <wink>.
Corollary question: Is there some reason the win32api stuff isn't in the core?
I *expect* Guido would like that, provided the code fit the Python style guide and the docs were bashed into LaTeX. That's a massive amount of no-fun work, and I don't expect Mark to volunteer for either.

The key difference is that kill() wants a PID, while TerminateProcess wants a handle. Now, we *could* add a kill() (assuming it is not already there) but that would not solve your specific problem, as you have a handle and you would then need a platform specific way to convert it to a PID. It seems too hard to win.
Yes, a higher-level execution API would be worthwhile, especially if that could be expressed using posix semantics as a fallback. I am thinking of what threading is to thread, this new API could be to the various spawn/exec/popen functions.
Corollary question: Is there some reason the win32api stuff isn't in the core?
Even if we ignore Tim's requirements ('cos I know I will <wink>) there is still alot of work, and a *huge* amount of code. Do we want win32api, all of the "win32*" modules in win32all, or all of win32all. The win32api modules seems very useful, and it is for trivial things - but once you start doing real things, the other win32 modules start becoming useful, and so it goes. On the other hand, if these extensions were in the core, I wouldn't personally be worrying about those damn hex literal warnings <wink>. Mark.

>> Shouldn't one of these solutions (or some variant) appear under the >> veneer of os.kill()? I realize the semantics might not be exactly >> the same Mark> The key difference is that kill() wants a PID, while Mark> TerminateProcess wants a handle. Posix.kill() wants a pid. Can't os.kill() want anything it wants? ;-) In particular, can't it test its arguments to see if it got a handle or a pid then "Do The Right Thing" (tm Spike Lee I think)? I guess I'm lobbying for os.kill() or something like it (os.retire()?) to be the terminator for os.spawn*, regardless what those functions return. It seems weird to be able to create processes on various platforms but not be able to kill them as well. For the python-dev types not on the spambayes list, I do have an application in mind. In my environment I need to tunnel SB's pop3proxy app through an ssh connection. Starting and stopping it works okay on my MacOSX system, and I presume it will under other Unix-based systems. I began thinking about whether this would port to other platforms and noticed that os.kill() is only supported under Unix. It may turn out that my desire is moot if ssh can't be run under Windows anyway. Skip

[Skip Montanaro]
Posix.kill() wants a pid. Can't os.kill() want anything it wants? ;-)
Yes. On Windows it wants a handle, because that's what spawn*() returns on Windows. But, again, Windows processes aren't intended to be killed externally.
In particular, can't it test its arguments to see if it got a handle or a pid then "Do The Right Thing" (tm Spike Lee I think)?
No, process handles and process ids are both just "little integers" on Windows.
Why do you need to kill a process externally? For example, why can't you make "please stop now" a part of the protocol, so that a process can terminate itself gracefully when told to?
It may turn out that my desire is moot if ssh can't be run under Windows anyway.

Tim Peters <tim.one@comcast.net> writes:
That sounds like FUD. Why is it that processes aren't intended to be killed? Because the assassin can't know what state the process is in, so the process may not complete correctly? This is a general problem with killing, not specific to Windows, and it never stopped a killer. Or can you crash the operating system or the killer process by terminating some other process?
Because the process did not respond to the protocol. Should I kill it anyway and send a bug report to Microsoft? Regards, Martin

[Tim]
[martin@v.loewis.de]
That sounds like FUD.
Argue w/ Microsoft -- you've read their docs.
It's easy to find long articles about the dangers on the net. Here's one I don't think has been posted before: http://tinyurl.com/35o6
It's certainly possible to crash Win9x by killing processes, and easy to hang the killer process (indeed, I have four shareware "process killers" on my home box, as no single one of them is able to kill everything -- sometimes I have a hung process, and three hung process killers trying to nuke it! Win98SE generally becomes too unstable to continue running at that point.).
Because the process did not respond to the protocol. Should I kill it anyway and send a bug report to Microsoft?
The questions were addressed to Skip about his specific app. It sounded to me like he wanted to kill() routinely, instead of pursuing a clean shutdown. The TerminateProcess function is used to unconditionally cause a process to exit. Use it only in extreme circumstances. The state of global data maintained by dynamic-link libraries (DLLs) may be compromised if TerminateProcess is used rather than ExitProcess. because TerminateProcess doesn't notify attached DLLs of process termination -- it's not solely the killed process's state that can get hosed.

Tim Peters <tim.one@comcast.net> writes:
That sounds like FUD.
Argue w/ Microsoft -- you've read their docs.
Apparently not the ones you've read. The documentation of TerminateProcess does not include any warning, except for the recommendation to only use it extreme circumstances, and that the global state maintained by DLLs may be compromised. Please correct me if I'm wrong, but on NT+, there isn't any global state maintained by DLLs that could get corrupted. I interpret the warning as suggesting that "normal" shutdown procedures should be used if possible.
It mentions a number of methods to find the window, then explains that sending WM_CLOSE may fail, to finally explain that TerminateProcess should always work, and that you may lose data by using it. This is exactly the same as on Unix: If you kill a process that was just saving a file, the file may get corrupted. If there were unsaved data, they are lost. This is no reason not to use TerminateProcess.
That sounds like a bug in the killers. TerminateProcess returns immediately, according to the documentation. Now, the process may not terminate if it is blocked in the kernel (the same issue exists on Unix, leading to zombie processes). If the killer then invokes WaitForProcessClose, it is not surprising if it hangs. Your observations suggest "Don't use TerminateProcess on Win9x". I would extend this warning to "Don't use Win9x" :-)
Can you explain what the "global state" of a DLL is? It may have global state on Win9x, and be "attached" to a process - but I understand there is nothing "global" on NT+; the code gets mapped into the process (which gets cleaned up when the process is terminated), and there are no shared data. Regards, Martin

Martin, I'm not interested in arguing about this. If you want to implement os.kill() for Windows, go ahead. I only ask that the docs repeat the vendor's warnings against using it. It's fine for adult use, where "adult" means you know you're courting trouble and are prepared to accept the consequences.

>> In my environment I need to tunnel SB's pop3proxy app through an ssh >> connection. Tim> Why do you need to kill a process externally? For example, why Tim> can't you make "please stop now" a part of the protocol, so that a Tim> process can terminate itself gracefully when told to? I start the background ssh process from within pop3proxy, so it seems to me I ought to be the one to terminate it. As for protocol, I'm not aware of another way to terminate a running ssh other than to call kill(2) with a specified signal. That's more-or-less the Unix way. I don't have the luxury of modifying ssh to understand some application-specific protocol. Skip

[Tim]
[Skip Montanaro]
I start the background ssh process from within pop3proxy, so it seems to me I ought to be the one to terminate it.
OK, that wasn't clear to me before.
No, I'm not asking you to be silly <wink>. The Unix signal model isn't going to fly for you on Windows regardless.
participants (7)
-
Greg Ewing
-
Greg Ward
-
Mark Hammond
-
martin@v.loewis.de
-
Skip Montanaro
-
Tim Peters
-
Tim Peters