@@ -165,6 +165,45 @@ async def main():
165165 loop .set_task_factory (self .factory )
166166 r .run (main ())
167167
168+ def test_all_tasks_from_other_thread_includes_eager_tasks (self ):
169+ # gh-152020: all_tasks() called from another thread used to drop
170+ # eager-started tasks on free-threaded builds.
171+ loop = asyncio .new_event_loop ()
172+
173+ async def wait_forever ():
174+ await asyncio .Event ().wait ()
175+
176+ def eager_factory (loop , coro , ** kwargs ):
177+ return self .factory (loop , coro , eager_start = True , ** kwargs )
178+
179+ async def setup ():
180+ loop .set_task_factory (eager_factory )
181+ eager = loop .create_task (wait_forever (), name = "EAGER" )
182+ loop .set_task_factory (None )
183+ normal = loop .create_task (wait_forever (), name = "NORMAL" )
184+ return eager , normal
185+
186+ async def teardown ():
187+ tasks = [t for t in asyncio .all_tasks ()
188+ if t is not asyncio .current_task ()]
189+ for t in tasks :
190+ t .cancel ()
191+ await asyncio .gather (* tasks , return_exceptions = True )
192+
193+ thread = threading .Thread (target = loop .run_forever )
194+ thread .start ()
195+ try :
196+ held = asyncio .run_coroutine_threadsafe (setup (), loop ).result ()
197+ names = {t .get_name () for t in asyncio .all_tasks (loop )}
198+ self .assertIn ("NORMAL" , names )
199+ self .assertIn ("EAGER" , names )
200+ del held
201+ finally :
202+ asyncio .run_coroutine_threadsafe (teardown (), loop ).result ()
203+ loop .call_soon_threadsafe (loop .stop )
204+ thread .join ()
205+ loop .close ()
206+
168207
169208class TestPyFreeThreading (TestFreeThreading , TestCase ):
170209
0 commit comments