Issue #12540: Prevent zombie IDLE processes on Windows due to changes
in os.kill(). Original patch by Eli Bendersky.
This commit is contained in:
commit
2ef905d449
|
@ -10,6 +10,7 @@ import time
|
||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
import types
|
import types
|
||||||
|
import subprocess
|
||||||
|
|
||||||
import linecache
|
import linecache
|
||||||
from code import InteractiveInterpreter
|
from code import InteractiveInterpreter
|
||||||
|
@ -37,11 +38,6 @@ from idlelib import macosxSupport
|
||||||
HOST = '127.0.0.1' # python execution server on localhost loopback
|
HOST = '127.0.0.1' # python execution server on localhost loopback
|
||||||
PORT = 0 # someday pass in host, port for remote debug capability
|
PORT = 0 # someday pass in host, port for remote debug capability
|
||||||
|
|
||||||
try:
|
|
||||||
from signal import SIGTERM
|
|
||||||
except ImportError:
|
|
||||||
SIGTERM = 15
|
|
||||||
|
|
||||||
# Override warnings module to write to warning_stream. Initialize to send IDLE
|
# Override warnings module to write to warning_stream. Initialize to send IDLE
|
||||||
# internal warnings to the console. ScriptBinding.check_syntax() will
|
# internal warnings to the console. ScriptBinding.check_syntax() will
|
||||||
# temporarily redirect the stream to the shell window to display warnings when
|
# temporarily redirect the stream to the shell window to display warnings when
|
||||||
|
@ -344,13 +340,12 @@ class ModifiedInterpreter(InteractiveInterpreter):
|
||||||
self.port = PORT
|
self.port = PORT
|
||||||
|
|
||||||
rpcclt = None
|
rpcclt = None
|
||||||
rpcpid = None
|
rpcsubproc = None
|
||||||
|
|
||||||
def spawn_subprocess(self):
|
def spawn_subprocess(self):
|
||||||
if self.subprocess_arglist is None:
|
if self.subprocess_arglist is None:
|
||||||
self.subprocess_arglist = self.build_subprocess_arglist()
|
self.subprocess_arglist = self.build_subprocess_arglist()
|
||||||
args = self.subprocess_arglist
|
self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
|
||||||
self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
|
|
||||||
|
|
||||||
def build_subprocess_arglist(self):
|
def build_subprocess_arglist(self):
|
||||||
assert (self.port!=0), (
|
assert (self.port!=0), (
|
||||||
|
@ -365,12 +360,7 @@ class ModifiedInterpreter(InteractiveInterpreter):
|
||||||
command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
|
command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
|
||||||
else:
|
else:
|
||||||
command = "__import__('run').main(%r)" % (del_exitf,)
|
command = "__import__('run').main(%r)" % (del_exitf,)
|
||||||
if sys.platform[:3] == 'win' and ' ' in sys.executable:
|
return [sys.executable] + w + ["-c", command, str(self.port)]
|
||||||
# handle embedded space in path by quoting the argument
|
|
||||||
decorated_exec = '"%s"' % sys.executable
|
|
||||||
else:
|
|
||||||
decorated_exec = sys.executable
|
|
||||||
return [decorated_exec] + w + ["-c", command, str(self.port)]
|
|
||||||
|
|
||||||
def start_subprocess(self):
|
def start_subprocess(self):
|
||||||
addr = (HOST, self.port)
|
addr = (HOST, self.port)
|
||||||
|
@ -428,7 +418,7 @@ class ModifiedInterpreter(InteractiveInterpreter):
|
||||||
pass
|
pass
|
||||||
# Kill subprocess, spawn a new one, accept connection.
|
# Kill subprocess, spawn a new one, accept connection.
|
||||||
self.rpcclt.close()
|
self.rpcclt.close()
|
||||||
self.unix_terminate()
|
self.terminate_subprocess()
|
||||||
console = self.tkconsole
|
console = self.tkconsole
|
||||||
was_executing = console.executing
|
was_executing = console.executing
|
||||||
console.executing = False
|
console.executing = False
|
||||||
|
@ -469,21 +459,20 @@ class ModifiedInterpreter(InteractiveInterpreter):
|
||||||
self.rpcclt.close()
|
self.rpcclt.close()
|
||||||
except AttributeError: # no socket
|
except AttributeError: # no socket
|
||||||
pass
|
pass
|
||||||
self.unix_terminate()
|
self.terminate_subprocess()
|
||||||
self.tkconsole.executing = False
|
self.tkconsole.executing = False
|
||||||
self.rpcclt = None
|
self.rpcclt = None
|
||||||
|
|
||||||
def unix_terminate(self):
|
def terminate_subprocess(self):
|
||||||
"UNIX: make sure subprocess is terminated and collect status"
|
"Make sure subprocess is terminated"
|
||||||
if hasattr(os, 'kill'):
|
|
||||||
try:
|
try:
|
||||||
os.kill(self.rpcpid, SIGTERM)
|
self.rpcsubproc.kill()
|
||||||
except OSError:
|
except OSError:
|
||||||
# process already terminated:
|
# process already terminated
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
os.waitpid(self.rpcpid, 0)
|
self.rpcsubproc.wait()
|
||||||
except OSError:
|
except OSError:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -249,6 +249,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #12540: Prevent zombie IDLE processes on Windows due to changes
|
||||||
|
in os.kill().
|
||||||
|
|
||||||
- Issue #12683: urlparse updated to include svn as schemes that uses relative
|
- Issue #12683: urlparse updated to include svn as schemes that uses relative
|
||||||
paths. (svn from 1.5 onwards support relative path).
|
paths. (svn from 1.5 onwards support relative path).
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue