@@ -3767,29 +3767,28 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
37673767 return NULL ;
37683768 }
37693769 int err = 0 ;
3770-
3771- // The linked list holds borrowed references to the tasks
3772- // so before reading from it, all other threads
3773- // are stopped using stop the world event so that
3774- // no task could be concurrently deallocated while being
3775- // added to the list.
3776- // The state critical section need not to be held as
3777- // all other threads are paused.
3778- PyInterpreterState * interp = PyInterpreterState_Get ();
3779- _PyEval_StopTheWorld (interp );
3780-
3770+ ASYNCIO_STATE_LOCK (state );
37813771 struct llist_node * node ;
3772+
37823773 llist_for_each_safe (node , & state -> asyncio_tasks_head ) {
37833774 TaskObj * task = llist_data (node , TaskObj , task_node );
3784- if (PyList_Append (tasks , (PyObject * )task ) < 0 ) {
3785- Py_DECREF (tasks );
3786- Py_DECREF (loop );
3787- err = 1 ;
3788- break ;
3775+ // The linked list holds borrowed references to task
3776+ // as such it is possible that it can concurrently
3777+ // deallocated while added to this list.
3778+ // To protect against concurrent deallocation,
3779+ // we first try to incref the task which would fail
3780+ // if it is concurrently getting deallocated in another thread,
3781+ // otherwise it gets added to the list.
3782+ if (_Py_TryIncref ((PyObject * )task )) {
3783+ if (_PyList_AppendTakeRef ((PyListObject * )tasks , (PyObject * )task ) < 0 ) {
3784+ Py_DECREF (tasks );
3785+ Py_DECREF (loop );
3786+ err = 1 ;
3787+ break ;
3788+ }
37893789 }
37903790 }
3791-
3792- _PyEval_StartTheWorld (interp );
3791+ ASYNCIO_STATE_UNLOCK (state );
37933792 if (err ) {
37943793 return NULL ;
37953794 }
0 commit comments