Skip to content

Commit 9b54ad3

Browse files
committed
Replace ASYNC_SCHEDULER_DEBUG with Console.debug.
1 parent 21f9d55 commit 9b54ad3

File tree

3 files changed

+58
-44
lines changed

3 files changed

+58
-44
lines changed

lib/async/scheduler.rb

+3-6
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
module Async
1717
# Handles scheduling of fibers. Implements the fiber scheduler interface.
1818
class Scheduler < Node
19-
# Whether to enable debug output.
20-
DEBUG = ENV.fetch("ASYNC_SCHEDULER_DEBUG", false) == "true"
21-
2219
# Raised when an operation is attempted on a closed scheduler.
2320
class ClosedError < RuntimeError
2421
# Create a new error.
@@ -391,9 +388,9 @@ def stop
391388
end
392389
rescue Interrupt => interrupt
393390
Thread.handle_interrupt(::SignalException => :never) do
394-
if DEBUG
395-
$stderr.puts "Scheduler interrupted: #{interrupt.inspect}"
396-
self.print_hierarchy($stderr)
391+
Console.debug(self) do |buffer|
392+
buffer.puts "Scheduler interrupted: #{interrupt.inspect}"
393+
self.print_hierarchy(buffer)
397394
end
398395

399396
self.stop

releases.md

+17-38
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,26 @@
22

33
## Unreleased
44

5-
### Async::Scheduler Debug
5+
### Async::Scheduler Debugging
66

7-
Occasionally on issues, I encounter people asking for help and I need more information. Pressing Ctrl-C to exit a hung program is common, but it doesn't provide enough information to diagnose the problem. I've added a new environment variable, `ASYNC_SCHEDULER_DEBUG=true` which will print out the current state of the scheduler when you press Ctrl-C.
7+
Occasionally on issues, I encounter people asking for help and I need more information. Pressing Ctrl-C to exit a hung program is common, but it usually doesn't provide enough information to diagnose the problem. Setting the `CONSOLE_LEVEL=debug` environment variable will now print additional information about the scheduler when you interrupt it, including a backtrace of the current tasks.
88

99
```
10-
> ASYNC_SCHEDULER_DEBUG=true bundle exec ruby ./test.rb
11-
^CScheduler interrupted: Interrupt
12-
#<Async::Reactor:0x0000000000000910 1 children (running)>
13-
#<Async::Task:0x0000000000000924 /home/samuel/Developer/socketry/async/lib/async/scheduler.rb:187:in `transfer' (running)>
14-
→ /home/samuel/Developer/socketry/async/lib/async/scheduler.rb:187:in `transfer'
15-
/home/samuel/Developer/socketry/async/lib/async/scheduler.rb:187:in `block'
16-
/home/samuel/Developer/socketry/async/lib/async/scheduler.rb:209:in `kernel_sleep'
17-
./test.rb:4:in `sleep'
18-
./test.rb:4:in `sleepy'
19-
./test.rb:10:in `sleepy'
20-
./test.rb:10:in `sleepy'
21-
./test.rb:10:in `sleepy'
22-
./test.rb:14:in `block in <main>'
23-
/home/samuel/Developer/socketry/async/lib/async/task.rb:197:in `block in run'
24-
/home/samuel/Developer/socketry/async/lib/async/task.rb:420:in `block in schedule'
25-
#<Async::Task:0x0000000000000938 /home/samuel/Developer/socketry/async/lib/async/scheduler.rb:187:in `transfer' (running)>
26-
→ /home/samuel/Developer/socketry/async/lib/async/scheduler.rb:187:in `transfer'
27-
/home/samuel/Developer/socketry/async/lib/async/scheduler.rb:187:in `block'
28-
/home/samuel/Developer/socketry/async/lib/async/scheduler.rb:209:in `kernel_sleep'
29-
./test.rb:4:in `sleep'
30-
./test.rb:4:in `sleepy'
31-
./test.rb:10:in `sleepy'
32-
./test.rb:10:in `sleepy'
33-
./test.rb:7:in `block in sleepy'
34-
/home/samuel/Developer/socketry/async/lib/async/task.rb:197:in `block in run'
35-
/home/samuel/Developer/socketry/async/lib/async/task.rb:420:in `block in schedule'
36-
/home/samuel/Developer/socketry/async/lib/async/scheduler.rb:319:in `select': Interrupt
37-
from /home/samuel/Developer/socketry/async/lib/async/scheduler.rb:319:in `run_once!'
38-
from /home/samuel/Developer/socketry/async/lib/async/scheduler.rb:355:in `run_once'
39-
from /home/samuel/Developer/socketry/async/lib/async/scheduler.rb:417:in `block in run'
40-
from /home/samuel/Developer/socketry/async/lib/async/scheduler.rb:388:in `block in run_loop'
41-
from /home/samuel/Developer/socketry/async/lib/async/scheduler.rb:385:in `handle_interrupt'
42-
from /home/samuel/Developer/socketry/async/lib/async/scheduler.rb:385:in `run_loop'
43-
from /home/samuel/Developer/socketry/async/lib/async/scheduler.rb:416:in `run'
44-
from /home/samuel/Developer/socketry/async/lib/kernel/async.rb:34:in `Async'
45-
from ./test.rb:13:in `<main>'
10+
> CONSOLE_LEVEL=debug bundle exec ruby ./test.rb
11+
^C 0.0s debug: Async::Reactor [oid=0x974] [ec=0x988] [pid=9116] [2024-11-08 14:12:03 +1300]
12+
| Scheduler interrupted: Interrupt
13+
| #<Async::Reactor:0x0000000000000974 1 children (running)>
14+
| #<Async::Task:0x000000000000099c /Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:185:in `transfer' (running)>
15+
| → /Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:185:in `transfer'
16+
| /Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:185:in `block'
17+
| /Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:207:in `kernel_sleep'
18+
| /Users/samuel/Developer/socketry/async/test.rb:7:in `sleep'
19+
| /Users/samuel/Developer/socketry/async/test.rb:7:in `sleepy'
20+
| /Users/samuel/Developer/socketry/async/test.rb:12:in `block in <top (required)>'
21+
| /Users/samuel/Developer/socketry/async/lib/async/task.rb:197:in `block in run'
22+
| /Users/samuel/Developer/socketry/async/lib/async/task.rb:420:in `block in schedule'
23+
/Users/samuel/Developer/socketry/async/lib/async/scheduler.rb:317:in `select': Interrupt
24+
... (backtrace continues) ...
4625
```
4726

4827
This gives better visibility into what the scheduler is doing, and should help diagnose issues.

test/async/scheduler.rb

+38
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
require "async/barrier"
99
require "net/http"
1010

11+
require "sus/fixtures/console"
12+
1113
describe Async::Scheduler do
14+
include_context Sus::Fixtures::Console::CapturedLogger
15+
1216
it "is supported" do
1317
expect(Async::Scheduler).to be(:supported?)
1418
end
@@ -209,4 +213,38 @@
209213
expect(child_task).not.to be(:transient?)
210214
end
211215
end
216+
217+
it "prints out the stack trace of the scheduler" do
218+
ready = Thread::Queue.new
219+
thread = Thread.current
220+
221+
scheduler = Async::Scheduler.new
222+
223+
# This will interrupt the scheduler once it's running:
224+
Thread.new do
225+
ready.pop
226+
thread.raise(Interrupt)
227+
end
228+
229+
expect do
230+
begin
231+
Fiber.set_scheduler(scheduler)
232+
233+
scheduler.run do
234+
while true
235+
sleep(0)
236+
ready.push(true)
237+
end
238+
end
239+
ensure
240+
Fiber.set_scheduler(nil)
241+
end
242+
end.to raise_exception(Interrupt)
243+
244+
expect_console.to have_logged(
245+
severity: be == :debug,
246+
subject: be == scheduler,
247+
message: be =~ /Scheduler interrupted/,
248+
)
249+
end
212250
end

0 commit comments

Comments
 (0)