Skip to content

Commit 2607892

Browse files
committed
[GR-41105] Fix IO#{wait,wait_readable,wait_writable} with a timeout > INT_MAX seconds
PullRequest: truffleruby/3495
2 parents 7dbf53c + 62eb3e6 commit 2607892

File tree

5 files changed

+56
-6
lines changed

5 files changed

+56
-6
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Bug fixes:
1717
* Disallow the marshaling of polyglot exceptions since we can't properly reconstruct them (@nirvdrum).
1818
* Fix `String#split` missing a value in its return array when called with a pattern of `" "` and a _limit_ value > 0 on a string with trailing whitespace where the limit hasn't been met (@nirvdrum).
1919
* Fix `Kernel#sleep` and `Mutex#sleep` for durations smaller than 1 millisecond (#2716, @eregon).
20+
* Fix `IO#{wait,wait_readable,wait_writable}` with a timeout > INT_MAX seconds (@eregon).
2021

2122
Compatibility:
2223

lib/truffle/io/wait.rb

+2-3
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@ def ready?
1717
Truffle::IOOperations.poll(self, Truffle::IOOperations::POLLIN, 0)
1818
end
1919

20-
def wait(timeout = nil)
20+
def wait_readable(timeout = nil)
2121
ensure_open_and_readable
2222
Truffle::IOOperations.poll(self, Truffle::IOOperations::POLLIN, timeout) ? self : nil
2323
end
24-
25-
alias_method :wait_readable, :wait
24+
alias_method :wait, :wait_readable
2625

2726
def wait_writable(timeout = nil)
2827
ensure_open_and_writable
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
require_relative '../../spec_helper'
2+
3+
require 'io/wait'
4+
5+
describe "IO#wait_readable" do
6+
before :each do
7+
@io = File.new(__FILE__ )
8+
end
9+
10+
after :each do
11+
@io.close
12+
end
13+
14+
it "waits for the IO to become readable with no timeout" do
15+
@io.wait_readable.should == @io
16+
end
17+
18+
it "waits for the IO to become readable with the given timeout" do
19+
@io.wait_readable(1).should == @io
20+
end
21+
22+
it "waits for the IO to become readable with the given large timeout" do
23+
@io.wait_readable(365 * 24 * 60 * 60).should == @io
24+
end
25+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
require_relative '../../spec_helper'
2+
3+
require 'io/wait'
4+
5+
describe "IO#wait_writable" do
6+
it "waits for the IO to become writable with no timeout" do
7+
STDOUT.wait_writable.should == STDOUT
8+
end
9+
10+
it "waits for the IO to become writable with the given timeout" do
11+
STDOUT.wait_writable(1).should == STDOUT
12+
end
13+
14+
it "waits for the IO to become writable with the given large timeout" do
15+
# Represents one year and is larger than a 32-bit int
16+
STDOUT.wait_writable(365 * 24 * 60 * 60).should == STDOUT
17+
end
18+
end

src/main/ruby/truffleruby/core/truffle/io_operations.rb

+10-3
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,16 @@ def self.poll(io, event_mask, timeout)
212212
raise ArgumentError, 'timeout must be positive' if timeout < 0
213213

214214
# Milliseconds, rounded down
215-
timeout = remaining_timeout = (timeout * 1_000).to_i
215+
timeout_ms = Primitive.rb_to_int((timeout * 1_000).to_i)
216+
while timeout_ms > 2147483647 # INT_MAX
217+
timeout_ms -= 2147483000
218+
ret = poll(io, event_mask, 2147483)
219+
return ret unless ret == false
220+
end
221+
222+
remaining_timeout = timeout_ms
216223
start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
217-
deadline = start + timeout
224+
deadline = start + timeout_ms
218225
else
219226
remaining_timeout = -1
220227
end
@@ -225,7 +232,7 @@ def self.poll(io, event_mask, timeout)
225232
if primitive_result < 0
226233
errno = Errno.errno
227234
if errno == Errno::EINTR::Errno
228-
if timeout
235+
if timeout_ms
229236
# Update timeout
230237
now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
231238
if now >= deadline

0 commit comments

Comments
 (0)