diff options
author | Julien Palard <julien@palard.fr> | 2018-11-04 22:40:32 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-04 22:40:32 (GMT) |
commit | 5d236cafd7126e640fb25541fcc7e0a494450143 (patch) | |
tree | f8b8e98702fc0e4e661d275309652f6fd7546fcc /Lib/test/_test_multiprocessing.py | |
parent | b4db249c9544fc4425c32feb86d610f3224ca3d8 (diff) | |
download | cpython-5d236cafd7126e640fb25541fcc7e0a494450143.zip cpython-5d236cafd7126e640fb25541fcc7e0a494450143.tar.gz cpython-5d236cafd7126e640fb25541fcc7e0a494450143.tar.bz2 |
bpo-19675: Terminate processes if construction of a pool is failing. (GH-5614)
Diffstat (limited to 'Lib/test/_test_multiprocessing.py')
-rw-r--r-- | Lib/test/_test_multiprocessing.py | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index dc59e9f..7993fcb 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3,6 +3,7 @@ # import unittest +import unittest.mock import queue as pyqueue import contextlib import time @@ -4635,6 +4636,48 @@ class TestSimpleQueue(unittest.TestCase): proc.join() +class TestPoolNotLeakOnFailure(unittest.TestCase): + + def test_release_unused_processes(self): + # Issue #19675: During pool creation, if we can't create a process, + # don't leak already created ones. + will_fail_in = 3 + forked_processes = [] + + class FailingForkProcess: + def __init__(self, **kwargs): + self.name = 'Fake Process' + self.exitcode = None + self.state = None + forked_processes.append(self) + + def start(self): + nonlocal will_fail_in + if will_fail_in <= 0: + raise OSError("Manually induced OSError") + will_fail_in -= 1 + self.state = 'started' + + def terminate(self): + self.state = 'stopping' + + def join(self): + if self.state == 'stopping': + self.state = 'stopped' + + def is_alive(self): + return self.state == 'started' or self.state == 'stopping' + + with self.assertRaisesRegex(OSError, 'Manually induced OSError'): + p = multiprocessing.pool.Pool(5, context=unittest.mock.MagicMock( + Process=FailingForkProcess)) + p.close() + p.join() + self.assertFalse( + any(process.is_alive() for process in forked_processes)) + + + class MiscTestCase(unittest.TestCase): def test__all__(self): # Just make sure names in blacklist are excluded |