mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 08:25:20 +08:00
win32: Wait for the cancelled pipe I/O before returning
An interrupted pipe read or write returned right after `CancelIo`, which only requests the cancellation. Wait for the I/O to end and return what it transferred. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
47c12f2060
commit
c3b61b1243
2 files changed
+26
-10
Notes:
git
2026-10-25 02:58:05 +00:00
No files matched your search
@@ -1739,6 +1739,16 @@ class TestIO < Test::Unit::TestCase
|
||||
end
|
||||
end if /cygwin/ !~ RUBY_PLATFORM
|
||||
|
||||
def test_read_interrupted_by_wakeup
|
||||
with_pipe do |r, w|
|
||||
t = Thread.new { r.read }
|
||||
Thread.pass until t.stop?
|
||||
100_000.times { t.wakeup; w.write("x") }
|
||||
w.close
|
||||
assert_equal(100_000, t.value.size)
|
||||
end
|
||||
end
|
||||
|
||||
def test_read
|
||||
pipe(proc do |w|
|
||||
w.write "foobarbaz"
|
||||
|
||||
+16
-10
@@ -7464,13 +7464,17 @@ rb_w32_read_internal(int fd, void *buf, size_t size, rb_off_t *offset)
|
||||
errno = EINTR;
|
||||
else
|
||||
errno = map_errno(GetLastError());
|
||||
CloseHandle(ol.hEvent);
|
||||
CancelIo((HANDLE)_osfhnd(fd));
|
||||
rb_acrt_lowio_unlock_fh(fd);
|
||||
return -1;
|
||||
/* the read may have completed before the cancel, and the kernel
|
||||
* writes ol and buf until it ends either way */
|
||||
GetOverlappedResult((HANDLE)_osfhnd(fd), &ol, &read, TRUE);
|
||||
if (!read) {
|
||||
CloseHandle(ol.hEvent);
|
||||
rb_acrt_lowio_unlock_fh(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!GetOverlappedResult((HANDLE)_osfhnd(fd), &ol, &read, TRUE) &&
|
||||
else if (!GetOverlappedResult((HANDLE)_osfhnd(fd), &ol, &read, TRUE) &&
|
||||
(err = GetLastError()) != ERROR_HANDLE_EOF) {
|
||||
int ret = 0;
|
||||
if (err != ERROR_BROKEN_PIPE) {
|
||||
@@ -7577,13 +7581,15 @@ rb_w32_write_internal(int fd, const void *buf, size_t size, rb_off_t *offset)
|
||||
errno = EINTR;
|
||||
else
|
||||
errno = map_errno(GetLastError());
|
||||
CloseHandle(ol.hEvent);
|
||||
CancelIo((HANDLE)_osfhnd(fd));
|
||||
rb_acrt_lowio_unlock_fh(fd);
|
||||
return -1;
|
||||
GetOverlappedResult((HANDLE)_osfhnd(fd), &ol, &written, TRUE);
|
||||
if (!written) {
|
||||
CloseHandle(ol.hEvent);
|
||||
rb_acrt_lowio_unlock_fh(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!GetOverlappedResult((HANDLE)_osfhnd(fd), &ol, &written, TRUE)) {
|
||||
else if (!GetOverlappedResult((HANDLE)_osfhnd(fd), &ol, &written, TRUE)) {
|
||||
errno = map_errno(GetLastError());
|
||||
CloseHandle(ol.hEvent);
|
||||
CancelIo((HANDLE)_osfhnd(fd));
|
||||
|
||||
Reference in new issue
Block a user