]> granicus.if.org Git - python/commitdiff
Added kill, terminate and send_signal to subprocess.Popen
authorChristian Heimes <christian@cheimes.de>
Sat, 19 Apr 2008 02:23:57 +0000 (02:23 +0000)
committerChristian Heimes <christian@cheimes.de>
Sat, 19 Apr 2008 02:23:57 +0000 (02:23 +0000)
The bits and pieces for the Windows side were already in place. The POSIX side is trivial (as usual) and uses os.kill().

Doc/library/subprocess.rst
Lib/subprocess.py
Lib/test/test_subprocess.py
Misc/NEWS

index 901ce4d014b1ae032d356ebb941616f44ac9e7c6..09dbbd18c6eb62c68848a702d53a800b925b78e5 100644 (file)
@@ -208,6 +208,29 @@ Instances of the :class:`Popen` class have the following methods:
       size is large or unlimited.
 
 
+.. method:: Popen.send_signal(signal)
+
+   Sends the signal *signal* to the child.
+
+   .. note::
+
+      On Windows only SIGTERM is supported so far. It's an alias for
+      *terminate*.
+
+
+.. method:: Popen.terminate()
+
+   Stop the child. On Posix OSs the method sends SIGTERM to the
+   child. On Windows the Win32 API function TerminateProcess is called
+   to stop the child.
+
+
+.. method:: Popen.kill()
+
+   Kills the child. On Posix OSs the function sends SIGKILL to the child.
+   On Windows *kill* is an alias for *terminate*.
+
+
 The following attributes are also available:
 
 .. attribute:: Popen.stdin
index 975a924aba340367d55f95b7e76ff89fae63304d..dc639c953aab31de79b1121872d6f30a629453d7 100644 (file)
@@ -357,6 +357,7 @@ import os
 import types
 import traceback
 import gc
+import signal
 
 # Exception classes used by this module.
 class CalledProcessError(Exception):
@@ -384,6 +385,7 @@ if mswindows:
         from win32process import CreateProcess, STARTUPINFO, \
                                  GetExitCodeProcess, STARTF_USESTDHANDLES, \
                                  STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE
+        from win32process import TerminateProcess
         from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0
     else:
         from _subprocess import *
@@ -906,6 +908,21 @@ class Popen(object):
             self.wait()
             return (stdout, stderr)
 
+        def send_signal(self, sig):
+            """Send a signal to the process
+            """
+            if sig == signal.SIGTERM:
+                self.terminate()
+            else:
+                raise ValueError("Only SIGTERM is supported on Windows")
+
+        def terminate(self):
+            """Terminates the process
+            """
+            TerminateProcess(self._handle, 1)
+
+        kill = terminate
+
     else:
         #
         # POSIX methods
@@ -1184,6 +1201,21 @@ class Popen(object):
             self.wait()
             return (stdout, stderr)
 
+        def send_signal(self, sig):
+            """Send a signal to the process
+            """
+            os.kill(self.pid, sig)
+
+        def terminate(self):
+            """Terminate the process with SIGTERM
+            """
+            self.send_signal(signal.SIGTERM)
+
+        def kill(self):
+            """Kill the process with SIGKILL
+            """
+            self.send_signal(signal.SIGKILL)
+
 
 def _demo_posix():
     #
index 9886f3d8fa2cf1b2c7d2b5dd5f85e47a41b52ced..ccefb674b80748e55a2d0de78b5fb36f5e9baedf 100644 (file)
@@ -584,6 +584,29 @@ class ProcessTestCase(unittest.TestCase):
             os.remove(fname)
             self.assertEqual(rc, 47)
 
+        def test_send_signal(self):
+            p = subprocess.Popen([sys.executable,
+                              "-c", "input()"])
+
+            self.assert_(p.poll() is None, p.poll())
+            p.send_signal(signal.SIGINT)
+            self.assertNotEqual(p.wait(), 0)
+
+        def test_kill(self):
+            p = subprocess.Popen([sys.executable,
+                            "-c", "input()"])
+
+            self.assert_(p.poll() is None, p.poll())
+            p.kill()
+            self.assertEqual(p.wait(), -signal.SIGKILL)
+
+        def test_terminate(self):
+            p = subprocess.Popen([sys.executable,
+                            "-c", "input()"])
+
+            self.assert_(p.poll() is None, p.poll())
+            p.terminate()
+            self.assertEqual(p.wait(), -signal.SIGTERM)
 
     #
     # Windows tests
@@ -655,6 +678,29 @@ class ProcessTestCase(unittest.TestCase):
                                  ' -c "import sys; sys.exit(47)"')
             self.assertEqual(rc, 47)
 
+        def test_send_signal(self):
+            p = subprocess.Popen([sys.executable,
+                              "-c", "input()"])
+
+            self.assert_(p.poll() is None, p.poll())
+            p.send_signal(signal.SIGTERM)
+            self.assertNotEqual(p.wait(), 0)
+
+        def test_kill(self):
+            p = subprocess.Popen([sys.executable,
+                            "-c", "input()"])
+
+            self.assert_(p.poll() is None, p.poll())
+            p.kill()
+            self.assertNotEqual(p.wait(), 0)
+
+        def test_terminate(self):
+            p = subprocess.Popen([sys.executable,
+                            "-c", "input()"])
+
+            self.assert_(p.poll() is None, p.poll())
+            p.terminate()
+            self.assertNotEqual(p.wait(), 0)
 
 def test_main():
     test_support.run_unittest(ProcessTestCase)
index 6ae6e46942b4936ad4939c875eecac6dda8b9b73..660651a86b5e52658366ef28f03e9aed11eeefd8 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -18,6 +18,8 @@ Core and builtins
 Extensions Modules
 ------------------
 
+- Added kill, terminate and send_signal(sig) to subprocess.Popen.
+
 - Added phase(z) -> phi, polar(z) -> r, phi and rect(r, phi) -> z to the cmath
   module.