<div class="gmail_quote">Hi all,<br><br>Here is a patch to the IDLE shipped with Python 2.5.2 that I regard as a bug fix. Specifically, it makes IDLE terminate its subprocess on Windows with TerminateProcess (instead of just by closing a socket), and on UNIX with SIGKILL instead of SIGTERM. The Windows change is especially important, because without it IDLE rather often fails to end my programs in a timely fashion when I close the output window, restart the shell, or just press F5 to run the program again. I think, however, that the behavior on all platforms should be to terminate the user program immediately whether or not it cooperates; that's what I expect when I give such a command to an IDE, and a user program running disconnected from its output terminal is not a good thing.<br>
<br>I'm working on Windows at the moment, so I'd greatly appreciate it if someone on the list can test my changes on a platform that has os.kill.<br><br>I suspect that the code in run.py has some quirks that exacerbate the bad behavior without the patch (for example, why the 10 second timeout in MyHandler.exithook?), but my patch appears to make them irrelevant, as well as deal with really nasty ways that the running program could freeze itself up (e.g. a C extension that blocks without releasing the interpreter lock). If there are any platforms other than Windows without os.kill, it might be worth at least getting rid of the timeout.<br>
<br>Comments or questions?<br><br>Dave<br><br><br><blockquote style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;" class="gmail_quote">--- c:\temp\Python-2.5.2\lib\idlelib\PyShell.py 2006-10-12 03:57:24.000000000 -0400<br>
+++ c:\python25\lib\idlelib\PyShell.py 2008-05-14 17:09:29.958875000 -0400<br>@@ -12,6 +12,7 @@<br> import traceback<br> import types<br> import macosxSupport<br>+import subprocess<br> <br> import linecache<br> from code import InteractiveInterpreter<br>
@@ -39,10 +40,31 @@<br> IDENTCHARS = string.ascii_letters + string.digits + "_"<br> LOCALHOST = '<a href="http://127.0.0.1" target="_blank">127.0.0.1</a>'<br> <br>-try:<br>- from signal import SIGTERM<br>
-except ImportError:<br>
- SIGTERM = 15<br>+if hasattr(os, 'kill'):<br>+ try:<br>+ from signal import SIGKILL<br>+ except ImportError:<br>+ SIGTERM = 9<br>+<br>+ def kill( proc ):<br>+ try:<br>+ os.kill( proc.pid, SIGKILL )<br>
+ except OSError:<br>+ # process already terminated:<br>+ return<br>+ else:<br>+ try:<br>+ proc.wait()<br>+ except OSError:<br>+ return<br>
+elif sys.platform[:3] == 'win':<br>+ import ctypes<br>+ def kill( proc ):<br>+ ctypes.windll.kernel32.TerminateProcess( int(proc._handle), -1 )<br>+ proc.wait()<br>+else:<br>+ def kill( proc ):<br>
+ pass # Hope the RPC mechanism will do the job<br> <br> # Override warnings module to write to warning_stream. Initialize to send IDLE<br> # internal warnings to the console. ScriptBinding.check_syntax() will<br>
@@ -343,11 +365,11 @@<br> <br> port = 8833<br> rpcclt = None<br>- rpcpid = None<br>+ rpcproc = None<br> <br> def spawn_subprocess(self):<br> args = self.subprocess_arglist<br>- self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)<br>
+ self.rpcproc = subprocess.Popen( [sys.executable] + args[1:] )<br> <br> def build_subprocess_arglist(self):<br> w = ['-W' + s for s in sys.warnoptions]<br>@@ -463,17 +485,7 @@<br> <br> def unix_terminate(self):<br>
"UNIX: make sure subprocess is terminated and collect status"<br>- if hasattr(os, 'kill'):<br>- try:<br>- os.kill(self.rpcpid, SIGTERM)<br>- except OSError:<br>
- # process already terminated:<br>- return<br>- else:<br>- try:<br>- os.waitpid(self.rpcpid, 0)<br>- except OSError:<br>- return<br>
+ kill( self.rpcproc )<br> <br> def transfer_path(self):<br> self.runcommand("""if 1:<br><br></blockquote>
</div><br>