Skip to content

Commit fa51753

Browse files
committed
WIP
1 parent 061480f commit fa51753

File tree

3 files changed

+99
-60
lines changed

3 files changed

+99
-60
lines changed

lib/async/scheduler.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ def block(blocker, timeout)
234234
# @parameter blocker [Object] The object that was blocking the fiber.
235235
# @parameter fiber [Fiber] The fiber to unblock.
236236
def unblock(blocker, fiber)
237-
# $stderr.puts "unblock(#{blocker}, #{fiber})"
237+
# Fiber.blocking{$stderr.puts "unblock(#{blocker}, #{fiber})"}
238238

239239
# This operation is protected by the GVL:
240240
if selector = @selector
@@ -250,6 +250,8 @@ def unblock(blocker, fiber)
250250
#
251251
# @parameter duration [Numeric | Nil] The time in seconds to sleep, or if nil, indefinitely.
252252
def kernel_sleep(duration = nil)
253+
# Fiber.blocking{$stderr.puts "kernel_sleep(#{duration}, #{Fiber.current})"}
254+
253255
if duration
254256
self.block(nil, duration)
255257
else
@@ -365,12 +367,14 @@ def alive?
365367

366368
# Transfer control to the operation - this will stop the task.
367369
def transfer
370+
# Fiber.blocking{$stderr.puts "FiberInterrupt#transfer(#{@fiber}, #{@exception})"}
368371
@fiber.raise(@exception)
369372
end
370373
end
371374

372375
# Raise an exception on the specified fiber, waking up the event loop if necessary.
373376
def fiber_interrupt(fiber, exception)
377+
# Fiber.blocking{$stderr.puts "fiber_interrupt(#{fiber}, #{exception})"}
374378
unblock(nil, FiberInterrupt.new(fiber, exception))
375379
end
376380

test.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env ruby
2+
3+
require_relative 'lib/async'
4+
5+
Async do
6+
r, w = IO.pipe
7+
8+
read_thread = Thread.new do
9+
Thread.current.report_on_exception = false
10+
r.read(5)
11+
end
12+
13+
# Wait until read_thread blocks on I/O
14+
Thread.pass until read_thread.status == "sleep"
15+
16+
close_task = Async do
17+
r.close
18+
end
19+
20+
close_task.wait
21+
begin
22+
read_thread.join
23+
rescue => error
24+
puts "Caught exception: #{error.class} - #{error.message}"
25+
end
26+
end

test/io.rb

Lines changed: 68 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -93,126 +93,135 @@
9393

9494
with "#close" do
9595
it "can interrupt reading fiber when closing" do
96+
skip_unless_minimum_ruby_version("3.5")
97+
9698
r, w = IO.pipe
9799

98100
read_task = Async do
99-
r.read(5)
100-
nil
101-
rescue IOError => e
102-
e.to_s
101+
expect do
102+
r.read(5)
103+
end.to raise_exception(IOError, message: be =~ /stream closed/)
103104
end
104-
105+
105106
r.close
106-
107-
expect(read_task.wait).to be == "closed stream"
107+
read_task.wait
108108
end
109-
109+
110110
it "can interrupt reading fiber when closing from another fiber" do
111+
skip_unless_minimum_ruby_version("3.5")
112+
111113
r, w = IO.pipe
112-
114+
113115
read_task = Async do
114-
r.read(5)
115-
nil
116-
rescue IOError => e
117-
e.to_s
116+
expect do
117+
r.read(5)
118+
end.to raise_exception(IOError, message: be =~ /stream closed/)
118119
end
119-
120+
120121
close_task = Async do
121122
r.close
122123
end
123-
124+
124125
close_task.wait
125-
expect(read_task.wait).to be == "closed stream"
126+
read_task.wait
126127
end
127-
128+
128129
it "can interrupt reading fiber when closing from a new thread" do
130+
skip_unless_minimum_ruby_version("3.5")
131+
129132
r, w = IO.pipe
130-
133+
131134
read_task = Async do
132-
r.read(5)
133-
nil
134-
rescue IOError => e
135-
e.to_s
135+
expect do
136+
r.read(5)
137+
end.to raise_exception(IOError, message: be =~ /stream closed/)
136138
end
137-
139+
138140
close_thread = Thread.new do
139141
r.close
140142
end
141-
143+
142144
close_thread.value
143-
expect(read_task.wait).to be == "closed stream"
145+
read_task.wait
144146
end
145-
147+
146148
it "can interrupt reading fiber when closing from a fiber in a new thread" do
149+
skip_unless_minimum_ruby_version("3.5")
150+
147151
r, w = IO.pipe
148-
152+
149153
read_task = Async do
150-
r.read(5)
151-
nil
152-
rescue IOError => e
153-
e.to_s
154+
expect do
155+
r.read(5)
156+
end.to raise_exception(IOError, message: be =~ /stream closed/)
154157
end
155-
158+
156159
close_thread = Thread.new do
157160
close_task = Async do
158161
r.close
159162
end
160163
close_task.wait
161164
end
162-
165+
163166
close_thread.value
164-
expect(read_task.wait).to be == "closed stream"
167+
read_task.wait
165168
end
166-
169+
167170
it "can interrupt reading thread when closing from a fiber" do
171+
skip_unless_minimum_ruby_version("3.5")
172+
173+
$stderr.puts "---------------------------------"
168174
r, w = IO.pipe
169-
175+
170176
read_thread = Thread.new do
171177
Thread.current.report_on_exception = false
178+
puts "Reading in thread #{Thread.current}"
172179
r.read(5)
173-
nil
174-
rescue IOError => e
175-
e.to_s
180+
ensure
181+
puts "Thread #{Thread.current} finished reading"
176182
end
177-
183+
178184
# Wait until read_thread blocks on I/O
179-
while read_thread.status != "sleep"
180-
sleep(0.001)
181-
end
182-
185+
Thread.pass until read_thread.status == "sleep"
186+
183187
close_task = Async do
188+
puts "Closing in fiber #{Thread.current}"
184189
r.close
190+
ensure
191+
puts "Closed in fiber #{Thread.current}"
185192
end
186-
193+
187194
close_task.wait
188-
expect(read_thread.value).to be == "closed stream"
195+
196+
expect do
197+
read_thread.join
198+
end.to raise_exception(IOError, message: be =~ /stream closed/)
189199
end
190-
200+
191201
it "can interrupt reading fiber in a new thread when closing from a fiber" do
202+
skip_unless_minimum_ruby_version("3.5")
203+
192204
r, w = IO.pipe
193-
205+
194206
read_thread = Thread.new do
195207
Thread.current.report_on_exception = false
196208
read_task = Async do
197-
r.read(5)
198-
nil
199-
rescue IOError => e
200-
e.to_s
209+
expect do
210+
r.read(5)
211+
end.to raise_exception(IOError, message: be =~ /stream closed/)
201212
end
202213
read_task.wait
203214
end
204-
215+
205216
# Wait until read_thread blocks on I/O
206-
while read_thread.status != "sleep"
207-
sleep(0.001)
208-
end
209-
217+
Thread.pass until read_thread.status == "sleep"
218+
210219
close_task = Async do
211220
r.close
212221
end
213222
close_task.wait
214-
215-
expect(read_thread.value).to be == "closed stream"
223+
224+
read_thread.value
216225
end
217226
end
218227
end

0 commit comments

Comments
 (0)