Skip to content

Commit eafaff9

Browse files
Re-introduce support for io_close hook. (ruby#15434)
1 parent 941e70a commit eafaff9

File tree

2 files changed

+19
-10
lines changed

2 files changed

+19
-10
lines changed

io.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5551,18 +5551,9 @@ fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl)
55515551
fptr->stdio_file = 0;
55525552
fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
55535553

5554-
// wait for blocking operations to ensure they do not hit EBADF:
5554+
// Wait for blocking operations to ensure they do not hit EBADF:
55555555
rb_thread_io_close_wait(fptr);
55565556

5557-
// Disable for now.
5558-
// if (!done && fd >= 0) {
5559-
// VALUE scheduler = rb_fiber_scheduler_current();
5560-
// if (scheduler != Qnil) {
5561-
// VALUE result = rb_fiber_scheduler_io_close(scheduler, fptr->self);
5562-
// if (!UNDEF_P(result)) done = 1;
5563-
// }
5564-
// }
5565-
55665557
if (!done && stdio_file) {
55675558
// stdio_file is deallocated anyway even if fclose failed.
55685559
if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(error)) {
@@ -5574,6 +5565,15 @@ fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl)
55745565
done = 1;
55755566
}
55765567

5568+
VALUE scheduler = rb_fiber_scheduler_current();
5569+
if (!done && fd >= 0 && scheduler != Qnil) {
5570+
VALUE result = rb_fiber_scheduler_io_close(scheduler, RB_INT2NUM(fd));
5571+
5572+
if (!UNDEF_P(result)) {
5573+
done = RTEST(result);
5574+
}
5575+
}
5576+
55775577
if (!done && fd >= 0) {
55785578
// fptr->fd may be closed even if close fails. POSIX doesn't specify it.
55795579
// We assumes it is closed.
@@ -5724,10 +5724,12 @@ io_close_fptr(VALUE io)
57245724
if (!fptr) return 0;
57255725
if (fptr->fd < 0) return 0;
57265726

5727+
// This guards against multiple threads closing the same IO object:
57275728
if (rb_thread_io_close_interrupt(fptr)) {
57285729
/* calls close(fptr->fd): */
57295730
fptr_finalize_flush(fptr, FALSE, KEEPGVL);
57305731
}
5732+
57315733
rb_io_fptr_cleanup(fptr, FALSE);
57325734
return fptr;
57335735
}

test/fiber/scheduler.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,13 @@ def io_select(...)
255255
end.value
256256
end
257257

258+
# This hook is invoked by `IO#close`. Using a separate IO object
259+
# demonstrates that the close operation is asynchronous.
260+
def io_close(descriptor)
261+
Fiber.blocking{IO.for_fd(descriptor.to_i).close}
262+
return true
263+
end
264+
258265
# This hook is invoked by `Kernel#sleep` and `Thread::Mutex#sleep`.
259266
def kernel_sleep(duration = nil)
260267
# $stderr.puts [__method__, duration, Fiber.current].inspect

0 commit comments

Comments
 (0)