|
14 | 14 | from logging.handlers import QueueHandler |
15 | 15 | import os |
16 | 16 | import queue |
| 17 | +import signal |
17 | 18 | import sys |
18 | 19 | import threading |
19 | 20 | import time |
@@ -397,6 +398,33 @@ def test_hang_gh83386(self): |
397 | 398 | self.assertFalse(err) |
398 | 399 | self.assertEqual(out.strip(), b"apple") |
399 | 400 |
|
| 401 | + def test_hang_gh94440(self): |
| 402 | + """shutdown(wait=True) doesn't hang when a future was submitted and |
| 403 | + quickly canceled right before shutdown. |
| 404 | +
|
| 405 | + See https://github.com/python/cpython/issues/94440. |
| 406 | + """ |
| 407 | + if not hasattr(signal, 'alarm'): |
| 408 | + raise unittest.SkipTest( |
| 409 | + "Tested platform does not support the alarm signal") |
| 410 | + |
| 411 | + def timeout(_signum, _frame): |
| 412 | + raise RuntimeError("timed out waiting for shutdown") |
| 413 | + |
| 414 | + kwargs = {} |
| 415 | + if getattr(self, 'ctx', None): |
| 416 | + kwargs['mp_context'] = self.get_context() |
| 417 | + executor = self.executor_type(max_workers=1, **kwargs) |
| 418 | + executor.submit(int).result() |
| 419 | + old_handler = signal.signal(signal.SIGALRM, timeout) |
| 420 | + try: |
| 421 | + signal.alarm(5) |
| 422 | + executor.submit(int).cancel() |
| 423 | + executor.shutdown(wait=True) |
| 424 | + finally: |
| 425 | + signal.alarm(0) |
| 426 | + signal.signal(signal.SIGALRM, old_handler) |
| 427 | + |
400 | 428 |
|
401 | 429 | class ThreadPoolShutdownTest(ThreadPoolMixin, ExecutorShutdownTest, BaseTestCase): |
402 | 430 | def test_threads_terminate(self): |
|
0 commit comments