Skip to content

Commit efc8770

Browse files
committedDec 25, 2015
Merge pull request #3541 from rubinius/wait-readable-writable
Update raising of WaitReadable/WaitWritable exceptions
2 parents fde04fc + 6216f2d commit efc8770

File tree

6 files changed

+75
-14
lines changed

6 files changed

+75
-14
lines changed
 

‎kernel/common/io.rb

+16
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@ class EAGAINWaitWritable < Errno::EAGAIN
1414
include ::IO::WaitWritable
1515
end
1616

17+
class EWOULDBLOCKWaitReadable < Errno::EAGAIN
18+
include WaitReadable
19+
end
20+
21+
class EWOULDBLOCKWaitWritable < Errno::EAGAIN
22+
include WaitWritable
23+
end
24+
25+
class EINPROGRESSWaitReadable < Errno::EINPROGRESS
26+
include WaitReadable
27+
end
28+
29+
class EINPROGRESSWaitWritable < Errno::EINPROGRESS
30+
include WaitWritable
31+
end
32+
1733
# Import platform constants
1834

1935
SEEK_SET = Rubinius::Config['rbx.platform.io.SEEK_SET']

‎spec/ruby/core/io/read_nonblock_spec.rb

+2-6
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,8 @@
1111
@write.close rescue nil
1212
end
1313

14-
it "raises EAGAIN when there is no data" do
15-
lambda { @read.read_nonblock(5) }.should raise_error(Errno::EAGAIN)
16-
end
17-
18-
it "raises IO::WaitReadable when there is no data" do
19-
lambda { @read.read_nonblock(5) }.should raise_error(IO::WaitReadable)
14+
it "raises IO::EAGAINWaitReadable when there is no data" do
15+
lambda { @read.read_nonblock(5) }.should raise_error(IO::EAGAINWaitReadable)
2016
end
2117

2218
it "returns at most the number of bytes requested" do

‎spec/ruby/core/io/write_nonblock_spec.rb

+16
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,22 @@
3434
end
3535
end
3636

37+
describe 'IO#write_nonblock' do
38+
before do
39+
@read, @write = IO.pipe
40+
end
41+
42+
after do
43+
@read.close
44+
@write.close
45+
end
46+
47+
it 'raises IO::EAGAINWaitWritable when the operation would block' do
48+
proc { loop { @write.write_nonblock('a' * 10_000) } }
49+
.should raise_error(IO::EAGAINWaitWritable)
50+
end
51+
end
52+
3753
describe "IO#write_nonblock" do
3854
it_behaves_like :io_write, :write_nonblock
3955
end

‎vm/builtin/exception.cpp

+36-5
Original file line numberDiff line numberDiff line change
@@ -313,15 +313,46 @@ namespace rubinius {
313313
RubyException::raise(exc);
314314
}
315315

316-
void Exception::errno_eagain_error(STATE, const char* reason) {
316+
void Exception::errno_wait_readable(STATE, int error) {
317317
Exception* exc;
318-
Class* exc_class = as<Class>(G(io)->get_const(state, "EAGAINWaitReadable"));
318+
Class* exc_class;
319319

320-
String* message = nil<String>();
320+
if(error == EAGAIN) {
321+
exc_class = as<Class>(G(io)->get_const(state, "EAGAINWaitReadable"));
322+
}
323+
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
324+
else if(error == EWOULDBLOCK) {
325+
exc_class = as<Class>(G(io)->get_const(state, "EWOULDBLOCKWaitReadable"));
326+
}
327+
#endif
328+
else {
329+
exc_class = get_errno_error(state, Fixnum::from(error));
330+
}
321331

322-
if(reason) {
323-
message = String::create(state, reason);
332+
String* message = String::create(state, "read would block");
333+
334+
exc = make_errno_exception(state, exc_class, message, cNil);
335+
336+
RubyException::raise(exc);
337+
}
338+
339+
void Exception::errno_wait_writable(STATE, int error) {
340+
Exception* exc;
341+
Class* exc_class;
342+
343+
if(error == EAGAIN) {
344+
exc_class = as<Class>(G(io)->get_const(state, "EAGAINWaitWritable"));
324345
}
346+
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
347+
else if(error == EWOULDBLOCK) {
348+
exc_class = as<Class>(G(io)->get_const(state, "EWOULDBLOCKWaitWritable"));
349+
}
350+
#endif
351+
else {
352+
exc_class = get_errno_error(state, Fixnum::from(error));
353+
}
354+
355+
String* message = String::create(state, "write would block");
325356

326357
exc = make_errno_exception(state, exc_class, message, cNil);
327358

‎vm/builtin/exception.hpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ namespace rubinius {
8888

8989
static void errno_error(STATE, const char* reason = NULL, int ern = 0,
9090
const char* entity = 0);
91-
static void errno_eagain_error(STATE, const char* reason);
91+
92+
static void errno_wait_readable(STATE, int error);
93+
static void errno_wait_writable(STATE, int error);
9294

9395
/**
9496
* Convenience predicates for checking the class of an

‎vm/builtin/io.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ namespace rubinius {
727727
int res = ::select(fd+1, &set, 0, 0, &tv);
728728

729729
if(res == 0) {
730-
Exception::errno_eagain_error(state, "no data ready");
730+
Exception::errno_wait_readable(state, EAGAIN);
731731
return 0;
732732
} else if(res <= 0) {
733733
Exception::errno_error(state, "read(2) failed");
@@ -834,7 +834,7 @@ namespace rubinius {
834834

835835
// We can use byte_address() here since we use an explicit size
836836
int n = ::write(descriptor_->to_native(), buf->byte_address(), buf_size);
837-
if(n == -1) Exception::errno_error(state, "write_nonblock");
837+
if(n == -1) Exception::errno_wait_writable(state, errno);
838838

839839
state->vm()->metrics().system.write_bytes += n;
840840

0 commit comments

Comments
 (0)
Please sign in to comment.