Index: Lib/subprocess.py
===================================================================
--- Lib/subprocess.py (revision 69127)
+++ Lib/subprocess.py (working copy)
@@ -951,18 +951,18 @@
self.wait()
return (stdout, stderr)
- def send_signal(self, sig):
+ def send_signal(self, sig, group=False):
"""Send a signal to the process
"""
if sig == signal.SIGTERM:
- self.terminate()
+ self.terminate(group=group)
else:
raise ValueError("Only SIGTERM is supported on Windows")
- def terminate(self):
+ def terminate(self, group=False):
"""Terminates the process
"""
- TerminateProcess(self._handle, 1)
+ TerminateProcess(self._handle, 1, group)
kill = terminate
@@ -1069,6 +1069,11 @@
if self.pid == 0:
# Child
try:
+ # If we're on unix, register the process in this process's
+ # subgroup.
+ if not mswindows:
+ os.setpgid(0, 0)
+
# Close parent's pipe ends
if p2cwrite is not None:
os.close(p2cwrite)
@@ -1254,20 +1259,23 @@
self.wait()
return (stdout, stderr)
- def send_signal(self, sig):
+ def send_signal(self, sig, group=False):
"""Send a signal to the process
"""
- os.kill(self.pid, sig)
+ if group:
+ os.killpg(self.pid, sig)
+ else:
+ os.kill(self.pid, sig)
- def terminate(self):
+ def terminate(self, group=False):
"""Terminate the process with SIGTERM
"""
- self.send_signal(signal.SIGTERM)
+ self.send_signal(signal.SIGTERM, group)
- def kill(self):
+ def kill(self, group=False):
"""Kill the process with SIGKILL
"""
- self.send_signal(signal.SIGKILL)
+ self.send_signal(signal.SIGKILL, group)
def _demo_posix():
Index: PC/_subprocess.c
===================================================================
--- PC/_subprocess.c (revision 69127)
+++ PC/_subprocess.c (working copy)
@@ -452,11 +452,17 @@
HANDLE process;
int exit_code;
- if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:TerminateProcess",
+ int group = 0;
+
+ if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i|i:TerminateProcess",
&process, &exit_code))
return NULL;
- result = TerminateProcess(process, exit_code);
+ if (group) {
+ result = TerminateJobObject(process, exit_code);
+ } else {
+ result = TerminateProcess(process, exit_code);
+ }
if (! result)
return PyErr_SetFromWindowsErr(GetLastError());
Index: Lib/test/test_subprocess.py
===================================================================
--- Lib/test/test_subprocess.py (revision 69127)
+++ Lib/test/test_subprocess.py (working copy)
@@ -644,6 +644,13 @@
p.send_signal(signal.SIGINT)
self.assertNotEqual(p.wait(), 0)
+ p = subprocess.Popen([sys.executable,
+ "-c", "input()"])
+
+ self.assert_(p.poll() is None, p.poll())
+ p.send_signal(signal.SIGINT, group=True)
+ self.assertNotEqual(p.wait(), 0)
+
def DISABLED_test_kill(self):
p = subprocess.Popen([sys.executable,
"-c", "input()"])
@@ -652,6 +659,13 @@
p.kill()
self.assertEqual(p.wait(), -signal.SIGKILL)
+ p = subprocess.Popen([sys.executable,
+ "-c", "input()"])
+
+ self.assert_(p.poll() is None, p.poll())
+ p.kill(group=True)
+ self.assertEqual(p.wait(), -signal.SIGKILL)
+
def DISABLED_test_terminate(self):
p = subprocess.Popen([sys.executable,
"-c", "input()"])
@@ -660,6 +674,13 @@
p.terminate()
self.assertEqual(p.wait(), -signal.SIGTERM)
+ p = subprocess.Popen([sys.executable,
+ "-c", "input()"])
+
+ self.assert_(p.poll() is None, p.poll())
+ p.terminate(group=True)
+ self.assertEqual(p.wait(), -signal.SIGTERM)
+
#
# Windows tests
#