|
11 | 11 | import traceback |
12 | 12 | from asyncio import CancelledError |
13 | 13 | from collections.abc import AsyncGenerator, Awaitable, Callable, Iterable, Sequence |
14 | | -from contextlib import AsyncExitStack, suppress |
| 14 | +from contextlib import AsyncExitStack |
15 | 15 | from datetime import timedelta |
16 | 16 | from functools import partial |
17 | 17 | from http import HTTPStatus |
@@ -763,19 +763,29 @@ def sigint_handler() -> None: |
763 | 763 |
|
764 | 764 | run_task = asyncio.create_task(self._run_crawler(), name='run_crawler_task') |
765 | 765 |
|
| 766 | + loop = asyncio.get_running_loop() |
| 767 | + remove_sigint_handler: Callable[[], object] | None = None |
| 768 | + |
766 | 769 | # `add_signal_handler` works only in the main thread |
767 | 770 | if threading.current_thread() is threading.main_thread(): |
768 | | - with suppress(NotImplementedError): # event loop signal handlers are not supported on Windows |
769 | | - asyncio.get_running_loop().add_signal_handler(signal.SIGINT, sigint_handler) |
| 771 | + try: |
| 772 | + loop.add_signal_handler(signal.SIGINT, sigint_handler) |
| 773 | + remove_sigint_handler = partial(loop.remove_signal_handler, signal.SIGINT) |
| 774 | + except NotImplementedError: |
| 775 | + # Windows event loops, such as the default `ProactorEventLoop`, don't support `add_signal_handler`. |
| 776 | + # Like `asyncio.Runner`, set the handler with `signal.signal` and pass the call to the event loop. |
| 777 | + previous_sigint_handler = signal.signal( |
| 778 | + signal.SIGINT, lambda *_: loop.call_soon_threadsafe(sigint_handler) |
| 779 | + ) |
| 780 | + remove_sigint_handler = partial(signal.signal, signal.SIGINT, previous_sigint_handler) |
770 | 781 |
|
771 | 782 | try: |
772 | 783 | await run_task |
773 | 784 | except CancelledError: |
774 | 785 | pass |
775 | 786 | finally: |
776 | | - if threading.current_thread() is threading.main_thread(): |
777 | | - with suppress(NotImplementedError): |
778 | | - asyncio.get_running_loop().remove_signal_handler(signal.SIGINT) |
| 787 | + if remove_sigint_handler is not None: |
| 788 | + remove_sigint_handler() |
779 | 789 |
|
780 | 790 | if self._statistics.error_tracker.total > 0: |
781 | 791 | self._logger.info( |
|
0 commit comments