Bug report
Bug description:
On a free-threading build asyncio.all_tasks() called from a thread other than the one running loop silently drops eager-started tasks
Reproducer:
import asyncio
import sys
import threading
async def forever():
await asyncio.Event().wait()
async def setup():
loop = asyncio.get_running_loop()
loop.set_task_factory(asyncio.eager_task_factory)
loop.create_task(forever(), name="EAGER")
loop.set_task_factory(None)
loop.create_task(forever(), name="NORMAL")
loop = asyncio.new_event_loop()
threading.Thread(target=loop.run_forever, daemon=True).start()
asyncio.run_coroutine_threadsafe(setup(), loop).result()
print("GIL enabled:", sys._is_gil_enabled())
print("all_tasks:", sorted(t.get_name() for t in asyncio.all_tasks(loop)))
Expected output is all_tasks: ['EAGER', 'NORMAL'] but actually we have all_tasks: ['NORMAL']
Proposed fix is to add _PyObject_SetMaybeWeakref in register_task
static void
register_task(_PyThreadStateImpl *ts, TaskObj *task)
{
if (task->task_node.next != NULL) {
// already registered
assert(task->task_node.prev != NULL);
return;
}
#ifdef Py_GIL_DISABLED
_PyObject_SetMaybeWeakref((PyObject *)task);
#endif
struct llist_node *head = &ts->asyncio_tasks_head;
llist_insert_tail(head, &task->task_node);
}
CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
Linked PRs
Bug report
Bug description:
On a free-threading build
asyncio.all_tasks()called from a thread other than the one running loop silently drops eager-started tasksReproducer:
Expected output is
all_tasks: ['EAGER', 'NORMAL']but actually we haveall_tasks: ['NORMAL']Proposed fix is to add
_PyObject_SetMaybeWeakrefinregister_taskCPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
Linked PRs