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
2 changes: 2 additions & 0 deletions Lib/multiprocessing/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import sys
import signal
import itertools
import threading
from _weakrefset import WeakSet

#
Expand Down Expand Up @@ -311,6 +312,7 @@ def _bootstrap(self):
sys.stderr.write('Process %s:\n' % self.name)
traceback.print_exc()
finally:
threading._shutdown()
util.info('process exiting with exitcode %d' % exitcode)
sys.stdout.flush()
sys.stderr.flush()
Expand Down
26 changes: 26 additions & 0 deletions Lib/test/_test_multiprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,32 @@ def test_child_fd_inflation(self):
p.join()
close_queue(q)

@classmethod
def _test_wait_for_threads(self, evt):
def func1():
time.sleep(0.5)
evt.set()

def func2():
time.sleep(20)
evt.clear()

threading.Thread(target=func1).start()
threading.Thread(target=func2, daemon=True).start()

def test_wait_for_threads(self):
# A child process should wait for non-daemonic threads to end
# before exiting
if self.TYPE == 'threads':
self.skipTest('test not appropriate for {}'.format(self.TYPE))

evt = self.Event()
proc = self.Process(target=self._test_wait_for_threads, args=(evt,))
proc.start()
proc.join()
self.assertTrue(evt.is_set())


#
#
#
Expand Down
3 changes: 3 additions & 0 deletions Lib/threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,9 @@ def _shutdown():
# the main thread's tstate_lock - that won't happen until the interpreter
# is nearly dead. So we release it here. Note that just calling _stop()
# isn't enough: other threads may already be waiting on _tstate_lock.
if _main_thread._is_stopped:
# _shutdown() was already called
return
tlock = _main_thread._tstate_lock
# The main thread isn't finished yet, so its thread state lock can't have
# been released.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Non-daemonic threads created by a multiprocessing.Process are now joined on
child exit.