@@ -156,3 +156,60 @@ async def cancel_sleep():
156156
157157 await loop .run_asyncio (cancel_sleep )
158158 assert owch == 0
159+
160+
161+ @pytest .mark .trio
162+ async def test_wrong_context_manager_order ():
163+ async def work_in_asyncio ():
164+ await asyncio .sleep (0 )
165+
166+ async def runner (* , task_status = trio .TASK_STATUS_IGNORED ):
167+ await trio_asyncio .run_asyncio (work_in_asyncio )
168+ try :
169+ task_status .started ()
170+ await trio .sleep_forever ()
171+ finally :
172+ await trio_asyncio .run_asyncio (work_in_asyncio )
173+
174+ async with trio .open_nursery () as nursery :
175+ async with trio_asyncio .open_loop ():
176+ await nursery .start (runner )
177+
178+
179+ @pytest .mark .trio
180+ async def test_keyboard_interrupt_teardown ():
181+ asyncio_loop_closed = trio .Event ()
182+
183+ async def work_in_trio_no_matter_what (* , task_status = trio .TASK_STATUS_IGNORED ):
184+ await trio_asyncio .run_asyncio (work_in_asyncio )
185+ try :
186+ # KeyboardInterrupt won't cancel this coroutine thanks to the shield
187+ with trio .open_cancel_scope (shield = True ):
188+ task_status .started ()
189+ await asyncio_loop_closed .wait ()
190+ finally :
191+ # Hence this call will be exceuted after run_asyncio_loop is cancelled
192+ await trio_asyncio .run_asyncio (work_in_asyncio )
193+
194+ async def work_in_asyncio ():
195+ await asyncio .sleep (0 )
196+
197+ async def run_asyncio_loop (nursery , * , task_status = trio .TASK_STATUS_IGNORED ):
198+ with trio .open_cancel_scope () as cancel_scope :
199+ try :
200+ async with trio_asyncio .open_loop ():
201+ # Starting a coroutine from here make it inherit the access
202+ # to the asyncio loop context manager
203+ await nursery .start (work_in_trio_no_matter_what )
204+ task_status .started (cancel_scope )
205+ await trio .sleep_forever ()
206+ finally :
207+ asyncio_loop_closed .set ()
208+
209+ import signal
210+ import threading
211+ with pytest .raises (KeyboardInterrupt ):
212+ async with trio .open_nursery () as nursery :
213+ await nursery .start (run_asyncio_loop , nursery )
214+ # Trigger KeyboardInterrupt that should propagate accross the coroutines
215+ signal .pthread_kill (threading .get_ident (), signal .SIGINT )
0 commit comments