Skip to content

Commit e686d8a

Browse files
committed
Implement C API rb_io_set_nonblock
1 parent 3a207a2 commit e686d8a

File tree

4 files changed

+29
-1
lines changed

4 files changed

+29
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Compatibility:
6060
* The `.bundle` file extension is now used for C extensions on macOS (#1819, #1837).
6161
* Implemented `Comparable#clamp` (#1517).
6262
* Implemented `rb_gc_register_mark_object` and `rb_enc_str_asciionly_p` (#1856, @chrisseaton).
63+
* Implemented `rb_io_set_nonblock` (#1741).
6364

6465
Performance:
6566

spec/ruby/optional/capi/ext/io_spec.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,14 @@ VALUE io_spec_rb_io_close(VALUE self, VALUE io) {
201201
return rb_io_close(io);
202202
}
203203

204+
VALUE io_spec_rb_io_set_nonblock(VALUE self, VALUE io) {
205+
rb_io_t* fp;
206+
GetOpenFile(io, fp);
207+
rb_io_set_nonblock(fp);
208+
int flags = fcntl(fp->fd, F_GETFL, 0);
209+
return flags & O_NONBLOCK ? Qtrue : Qfalse;
210+
}
211+
204212
/*
205213
* this is needed to ensure rb_io_wait_*able functions behave
206214
* predictably because errno may be set to unexpected values
@@ -225,6 +233,7 @@ void Init_io_spec(void) {
225233
rb_define_method(cls, "rb_io_check_readable", io_spec_rb_io_check_readable, 1);
226234
rb_define_method(cls, "rb_io_check_writable", io_spec_rb_io_check_writable, 1);
227235
rb_define_method(cls, "rb_io_check_closed", io_spec_rb_io_check_closed, 1);
236+
rb_define_method(cls, "rb_io_set_nonblock", io_spec_rb_io_set_nonblock, 1);
228237
rb_define_method(cls, "rb_io_taint_check", io_spec_rb_io_taint_check, 1);
229238
rb_define_method(cls, "rb_io_wait_readable", io_spec_rb_io_wait_readable, 2);
230239
rb_define_method(cls, "rb_io_wait_writable", io_spec_rb_io_wait_writable, 1);

spec/ruby/optional/capi/io_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@
151151
end
152152
end
153153

154+
describe "rb_io_set_nonblock" do
155+
it "returns true when nonblock flag is set" do
156+
@o.rb_io_set_nonblock(@io).should be_true
157+
end
158+
end
159+
154160
# NOTE: unlike the name might suggest in MRI this function checks if an
155161
# object is frozen, *not* if it's tainted.
156162
describe "rb_io_taint_check" do

src/main/c/cext/ruby.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4049,6 +4049,16 @@ int rb_cloexec_dup2(int oldfd, int newfd) {
40494049
rb_tr_error("rb_cloexec_dup2 not implemented");
40504050
}
40514051

4052+
static int rb_fd_set_nonblock(int fd) {
4053+
int oflags = fcntl(fd, F_GETFL);
4054+
if (oflags == -1)
4055+
return -1;
4056+
if (oflags & O_NONBLOCK)
4057+
return 0;
4058+
oflags |= O_NONBLOCK;
4059+
return fcntl(fd, F_SETFL, oflags);
4060+
}
4061+
40524062
int rb_cloexec_pipe(int fildes[2]) {
40534063
rb_tr_error("rb_cloexec_pipe not implemented");
40544064
}
@@ -4586,7 +4596,9 @@ VALUE rb_io_set_write_io(VALUE io, VALUE w) {
45864596
}
45874597

45884598
void rb_io_set_nonblock(rb_io_t *fptr) {
4589-
rb_tr_error("rb_io_set_nonblock not implemented");
4599+
if (rb_fd_set_nonblock(fptr->fd) != 0) {
4600+
rb_sys_fail("rb_io_set_nonblock failed");
4601+
}
45904602
}
45914603

45924604
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size) {

0 commit comments

Comments
 (0)