@@ -114,12 +114,45 @@ def test_cumulative_timeouts_less_than_close_plus_buffer():
114114 ) < 1 + _CLOSE_TIMEOUT + _LOADED_SYSTEM_TIMEOUT
115115
116116
117+ @pytest .mark .asyncio
117118async def test_run_coro_with_timeout () -> None :
118119 """Test running a coroutine with a timeout raises EventLoopBlocked."""
119120 loop = asyncio .get_event_loop ()
121+ task = None
122+
123+ async def _saved_sleep_task ():
124+ nonlocal task
125+ task = asyncio .create_task (asyncio .sleep (0.2 ))
126+ await task
120127
121128 def _run_in_loop ():
122- aioutils .run_coro_with_timeout (asyncio . sleep ( 0.3 ), loop , 0.1 )
129+ aioutils .run_coro_with_timeout (_saved_sleep_task ( ), loop , 0.1 )
123130
124131 with pytest .raises (EventLoopBlocked ), patch .object (aioutils , "_LOADED_SYSTEM_TIMEOUT" , 0.0 ):
125132 await loop .run_in_executor (None , _run_in_loop )
133+
134+ # ensure the thread is shutdown
135+ task .cancel ()
136+ await asyncio .sleep (0 )
137+ await _shutdown_default_executor (loop )
138+
139+
140+ # Remove this when we drop support for older python versions
141+ # since we can use loop.shutdown_default_executor() in 3.9+
142+ async def _shutdown_default_executor (loop : asyncio .AbstractEventLoop ) -> None :
143+ """Backport of cpython 3.9 schedule the shutdown of the default executor."""
144+ future = loop .create_future ()
145+
146+ def _do_shutdown () -> None :
147+ try :
148+ loop ._default_executor .shutdown (wait = True ) # type: ignore # pylint: disable=protected-access
149+ loop .call_soon_threadsafe (future .set_result , None )
150+ except Exception as ex : # pylint: disable=broad-except
151+ loop .call_soon_threadsafe (future .set_exception , ex )
152+
153+ thread = threading .Thread (target = _do_shutdown )
154+ thread .start ()
155+ try :
156+ await future
157+ finally :
158+ thread .join ()
0 commit comments