diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py index 8e7ffb971d26..51b2f21f26b3 100644 --- a/python/helpers/pydev/pydevd.py +++ b/python/helpers/pydev/pydevd.py @@ -173,10 +173,22 @@ class CheckOutputThread(PyDBDaemonThread): except: traceback.print_exc() + self.wait_pydb_threads_to_finish() + self.killReceived = True self.py_db.check_output_redirect() + def wait_pydb_threads_to_finish(self, timeout=0.5): + pydev_log.debug("Waiting for pydb daemon threads to finish") + pydb_daemon_threads = self.created_pydb_daemon_threads + started_at = time.time() + while time.time() < started_at + timeout: + if len(pydb_daemon_threads) == 1 and pydb_daemon_threads.get(self, None): + return + time.sleep(0.01) + pydev_log.debug("The following pydb threads may not finished correctly: %s" + % ', '.join([t.getName() for t in pydb_daemon_threads if t is not self])) def do_kill_pydev_thread(self): self.killReceived = True @@ -1311,6 +1323,9 @@ def _locked_settrace( global bufferStdOutToServer global bufferStdErrToServer + # Reset created PyDB daemon threads after fork - parent threads don't exist in a child process. + PyDBDaemonThread.created_pydb_daemon_threads = {} + if not connected: pydevd_vm_type.setup_type() diff --git a/python/testData/debug/test_multiprocess_pool.py b/python/testData/debug/test_multiprocess_pool.py new file mode 100644 index 000000000000..2392ffb0d832 --- /dev/null +++ b/python/testData/debug/test_multiprocess_pool.py @@ -0,0 +1,9 @@ +from __future__ import print_function +from multiprocessing import Pool +from time import sleep +pool = Pool(4) +pool.map(print, ['1', '2', '3']) +pool.close() +pool.join() +sleep(1) +print('Done') diff --git a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java index 1cd3cad39679..7895516664d0 100644 --- a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java +++ b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java @@ -827,6 +827,22 @@ public class PythonDebuggerTest extends PyEnvTestCase { }); } + @Test + public void testMultiprocessPool() { + runPythonTest(new PyDebuggerTask("/debug", "test_multiprocess_pool.py") { + @Override + protected void init() { + setMultiprocessDebug(true); + } + + @Override + public void testing() throws Exception { + waitForOutput("Done"); + assertFalse(output().contains("KeyboardInterrupt")); + } + }); + } + @Test public void testPythonSubprocessWithCParameter() { runPythonTest(new PyDebuggerTask("/debug", "test_python_subprocess_with_c_parameter.py") {