Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Doc/library/multiprocessing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,12 @@ The :mod:`multiprocessing` package mostly replicates the API of the
acquired a lock or semaphore etc. then terminating it is liable to
cause other processes to deadlock.

.. method:: kill()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since this is a new method, you need a versionadded marker a well (see above the sentinel attribute for an example).


Same as :meth:`terminate()` but using the ``SIGKILL`` signal on Unix.

.. versionadded:: 3.7

.. method:: close()

Close the :class:`Process` object, releasing all resources associated
Expand Down
10 changes: 8 additions & 2 deletions Lib/multiprocessing/popen_fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,22 @@ def wait(self, timeout=None):
return self.poll(os.WNOHANG if timeout == 0.0 else 0)
return self.returncode

def terminate(self):
def _send_signal(self, sig):
if self.returncode is None:
try:
os.kill(self.pid, signal.SIGTERM)
os.kill(self.pid, sig)
except ProcessLookupError:
pass
except OSError:
if self.wait(timeout=0.1) is None:
raise

def terminate(self):
self._send_signal(signal.SIGTERM)

def kill(self):
self._send_signal(signal.SIGKILL)

def _launch(self, process_obj):
code = 1
parent_r, child_w = os.pipe()
Expand Down
2 changes: 2 additions & 0 deletions Lib/multiprocessing/popen_spawn_win32.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,7 @@ def terminate(self):
if self.wait(timeout=1.0) is None:
raise

kill = terminate

def close(self):
self.finalizer()
7 changes: 7 additions & 0 deletions Lib/multiprocessing/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,13 @@ def terminate(self):
self._check_closed()
self._popen.terminate()

def kill(self):
'''
Terminate process; sends SIGKILL signal or uses TerminateProcess()
'''
self._check_closed()
self._popen.kill()

def join(self, timeout=None):
'''
Wait until child process terminates
Expand Down
22 changes: 15 additions & 7 deletions Lib/test/_test_multiprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,18 +277,18 @@ def test_process(self):
self.assertNotIn(p, self.active_children())

@classmethod
def _test_terminate(cls):
def _sleep_some(cls):
time.sleep(100)

@classmethod
def _test_sleep(cls, delay):
time.sleep(delay)

def test_terminate(self):
def _kill_process(self, meth):
if self.TYPE == 'threads':
self.skipTest('test not appropriate for {}'.format(self.TYPE))

p = self.Process(target=self._test_terminate)
p = self.Process(target=self._sleep_some)
p.daemon = True
p.start()

Expand All @@ -309,7 +309,7 @@ def test_terminate(self):
# XXX maybe terminating too soon causes the problems on Gentoo...
time.sleep(1)

p.terminate()
meth(p)

if hasattr(signal, 'alarm'):
# On the Gentoo buildbot waitpid() often seems to block forever.
Expand All @@ -333,9 +333,17 @@ def handler(*args):

p.join()

# sometimes get p.exitcode == 0 on Windows ...
return p.exitcode

def test_terminate(self):
exitcode = self._kill_process(multiprocessing.Process.terminate)
if os.name != 'nt':
self.assertEqual(exitcode, -signal.SIGTERM)

def test_kill(self):
exitcode = self._kill_process(multiprocessing.Process.kill)
if os.name != 'nt':
self.assertEqual(p.exitcode, -signal.SIGTERM)
self.assertEqual(exitcode, -signal.SIGKILL)

def test_cpu_count(self):
try:
Expand Down Expand Up @@ -462,7 +470,7 @@ def test_many_processes(self):
for p in procs:
self.assertEqual(p.exitcode, 0)

procs = [self.Process(target=self._test_terminate)
procs = [self.Process(target=self._sleep_some)
for i in range(N)]
for p in procs:
p.start()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Added multiprocessing.Process.kill method to terminate using the SIGKILL
signal on Unix.