Top level transient tasks are a bit odd. The event loop is considered already finished? and thus won't execute a single iteration. However, in order to terminate the event loop, any and all child tasks need to be stopped.
The following program causes a hang:
Async(transient:true) do
Async{sleep 1}
end
The top level task is created and executes, starting the child task.
The child task starts sleeping.
The event loop is considered finished because the top level task is transient.
The Scheduler#close method is invoked, which enters the terminate loop.
Task#stop is invoked on the top level task which stops the child task by raising and exception, but itself is not stopped yet. Raising an exception transfers to the child task.
Because run_once considers the scheduler is finished, it does not resume the parent task.
It continues to try and stop the top level task, but won't resume it (even thought it's in the ready list).
Infinite loop is achieved.
The fix, I think, is to avoid checking self.finished? when performing the termination loop. Tests added based on the original report.
Fixes https://github.com/socketry/async/issues/244.
Top level transient tasks are a bit odd. The event loop is considered already
finished?
and thus won't execute a single iteration. However, in order to terminate the event loop, any and all child tasks need to be stopped.The following program causes a hang:
Scheduler#close
method is invoked, which enters the terminate loop.Task#stop
is invoked on the top level task which stops the child task by raising and exception, but itself is not stopped yet. Raising an exception transfers to the child task.run_once
considers the scheduler is finished, it does not resume the parent task.The fix, I think, is to avoid checking
self.finished?
when performing the termination loop. Tests added based on the original report.Types of Changes
Contribution