Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work around lack of os.kill in win32. #2204

Merged
merged 2 commits into from Jul 26, 2012
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 13 additions & 29 deletions IPython/testing/iptest.py
Expand Up @@ -328,8 +328,8 @@ class IPTester(object):
params = None
#: list, arguments of system call to be made to call test runner
call_args = None
#: list, process ids of subprocesses we start (for cleanup)
pids = None
#: list, subprocesses we start (for cleanup)
processes = None
#: str, coverage xml output file
coverage_xml = None

Expand Down Expand Up @@ -370,19 +370,18 @@ def __init__(self, runner='iptest', params=None):
self.call_args.remove('--with-xml-coverage')
self.call_args = ["coverage", "run", "--source="+sect] + self.call_args[1:]

# Store pids of anything we start to clean up on deletion, if possible
# (on posix only, since win32 has no os.kill)
self.pids = []
# Store anything we start to clean up on deletion
self.processes = []

def _run_cmd(self):
# print >> sys.stderr, '*** CMD:', ' '.join(self.call_args) # dbg
subp = subprocess.Popen(self.call_args)
self.pids.append(subp.pid)
# If this fails, the pid will be left in self.pids and cleaned up
# later, but if the wait call succeeds, then we can clear the
# stored pid.
self.processes.append(subp)
# If this fails, the process will be left in self.processes and cleaned
# up later, but if the wait call succeeds, then we can clear the
# stored process.
retcode = subp.wait()
self.pids.pop()
self.processes.pop()
return retcode

def run(self):
Expand All @@ -398,28 +397,13 @@ def run(self):
subprocess.call(["coverage", "xml", "-o", self.coverage_xml])
return retcode

@staticmethod
def _kill(pid):
"""Attempt to kill the process on a best effort basis."""
if hasattr(os, 'kill'):
os.kill(pid, signal.SIGKILL)
elif sys.platform == 'win32':
# Python 2.6 on Windows doesn't have os.kill.
from ctypes import windll
PROCESS_TERMINATE = 1
handle = windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, pid)
windll.kernel32.TerminateProcess(handle, -1)
windll.kernel32.CloseHandle(handle)
else:
raise NotImplementedError

def __del__(self):
"""Cleanup on exit by killing any leftover processes."""
for pid in self.pids:
for subp in self.processes:
try:
print('Cleaning stale PID:', pid)
self._kill(pid)
except (OSError, NotImplementedError):
print('Cleaning stale PID: %d' % subp.pid)
subp.kill()
except: # (OSError, WindowsError) ?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe print a message here with just the exception in case a stale process fails to clean up? That way the user may know there's something worth looking at manually.

# This is just a best effort, if we fail or the process was
# really gone, ignore it.
pass
Expand Down