Skip to content

Commit 8ec6be8

Browse files
authored
Ensure transient tasks are correctly terminated. (#245)
1 parent 987683e commit 8ec6be8

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

lib/async/scheduler.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def scheduler_close
5050
def close
5151
# It's critical to stop all tasks. Otherwise they might be holding on to resources which are never closed/released correctly.
5252
until self.terminate
53-
self.run_once
53+
self.run_once!
5454
end
5555

5656
Kernel.raise "Closing scheduler with blocked operations!" if @blocked > 0
@@ -215,6 +215,16 @@ def run_once(timeout = nil)
215215
return false
216216
end
217217

218+
return run_once!(timeout)
219+
end
220+
221+
# Run one iteration of the event loop.
222+
#
223+
# When terminating the event loop, we already know we are finished. So we don't need to check the task tree. This is a logical requirement because `run_once` ignores transient tasks. For example, a single top level transient task is not enough to keep the reactor running, but during termination we must still process it in order to terminate child tasks.
224+
#
225+
# @parameter timeout [Float | Nil] The maximum timeout, or if nil, indefinite.
226+
# @returns [Boolean] Whether there is more work to do.
227+
private def run_once!(timeout = 0)
218228
interval = @timers.wait_interval
219229

220230
# If there is no interval to wait (thus no timers), and no tasks, we could be done:

test/async/reactor.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,20 @@
4040
sleep
4141
end
4242

43+
expect(reactor.run_once).to be == false
44+
expect(reactor).to be(:finished?)
45+
reactor.close
46+
end
47+
48+
it "terminates transient tasks with nested tasks" do
49+
task = reactor.async(transient: true) do |parent|
50+
parent.async do |child|
51+
sleep(1)
52+
end
53+
end
54+
4355
reactor.run_once
56+
expect(reactor).to be(:finished?)
4457
reactor.close
4558
end
4659

0 commit comments

Comments
 (0)