aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2023-12-27 00:36:56 +1300
committerGitHub <noreply@github.com>2023-12-27 00:36:56 +1300
commite5a4f757bdf5dc3d8c329ddd268432f9ecc7bff6 (patch)
tree55d01a7b891eda32e36b1f18e69ee6c1be8d0e7e
parentb1f67cf08eb0aaadfdc6893034b0653551141a10 (diff)
downloadruby-e5a4f757bdf5dc3d8c329ddd268432f9ecc7bff6.tar.gz
Fix Window private file mapping unlink EACCES issue. (#9358)
* Don't return early. * Add missing `mapping` assignment. * Make debug logs conditional.
-rw-r--r--io_buffer.c18
-rw-r--r--test/ruby/test_io_buffer.rb32
2 files changed, 26 insertions, 24 deletions
diff --git a/io_buffer.c b/io_buffer.c
index 3c47f659bc..7e580c8633 100644
--- a/io_buffer.c
+++ b/io_buffer.c
@@ -42,6 +42,8 @@ enum {
// This is used to validate the flags given by the user.
RB_IO_BUFFER_FLAGS_MASK = RB_IO_BUFFER_EXTERNAL | RB_IO_BUFFER_INTERNAL | RB_IO_BUFFER_MAPPED | RB_IO_BUFFER_SHARED | RB_IO_BUFFER_LOCKED | RB_IO_BUFFER_PRIVATE | RB_IO_BUFFER_READONLY,
+
+ RB_IO_BUFFER_DEBUG = 0,
};
struct rb_io_buffer {
@@ -113,6 +115,7 @@ io_buffer_map_file(struct rb_io_buffer *buffer, int descriptor, size_t size, rb_
}
HANDLE mapping = CreateFileMapping(file, NULL, protect, 0, 0, NULL);
+ if (RB_IO_BUFFER_DEBUG) fprintf(stderr, "io_buffer_map_file:CreateFileMapping -> %p\n", mapping);
if (!mapping) rb_sys_fail("io_buffer_map_descriptor:CreateFileMapping");
void *base = MapViewOfFile(mapping, access, (DWORD)(offset >> 32), (DWORD)(offset & 0xFFFFFFFF), size);
@@ -213,9 +216,13 @@ io_buffer_initialize(VALUE self, struct rb_io_buffer *buffer, void *base, size_t
buffer->size = size;
buffer->flags = flags;
RB_OBJ_WRITE(self, &buffer->source, source);
+
+#if defined(_WIN32)
+ buffer->mapping = NULL;
+#endif
}
-static int
+static void
io_buffer_free(struct rb_io_buffer *buffer)
{
if (buffer->base) {
@@ -247,18 +254,17 @@ io_buffer_free(struct rb_io_buffer *buffer)
buffer->size = 0;
buffer->flags = 0;
buffer->source = Qnil;
-
- return 1;
}
#if defined(_WIN32)
if (buffer->mapping) {
- CloseHandle(buffer->mapping);
+ if (RB_IO_BUFFER_DEBUG) fprintf(stderr, "io_buffer_free:CloseHandle -> %p\n", buffer->mapping);
+ if (!CloseHandle(buffer->mapping)) {
+ fprintf(stderr, "io_buffer_free:GetLastError -> %d\n", GetLastError());
+ }
buffer->mapping = NULL;
}
#endif
-
- return 0;
}
void
diff --git a/test/ruby/test_io_buffer.rb b/test/ruby/test_io_buffer.rb
index b4b63b1eda..321b6534ee 100644
--- a/test/ruby/test_io_buffer.rb
+++ b/test/ruby/test_io_buffer.rb
@@ -521,24 +521,20 @@ class TestIOBuffer < Test::Unit::TestCase
def test_private
Tempfile.create(%w"buffer .txt") do |file|
file.write("Hello World")
- file.close
- assert_separately(["-W0", "-", file.path], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- file = File.open(ARGV[0], "r+")
- buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::PRIVATE)
- begin
- assert buffer.private?
- refute buffer.readonly?
-
- buffer.set_string("J")
-
- # It was not changed because the mapping was private:
- file.seek(0)
- assert_equal "Hello World", file.read
- ensure
- buffer&.free
- end
- end;
+
+ buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::PRIVATE)
+ begin
+ assert buffer.private?
+ refute buffer.readonly?
+
+ buffer.set_string("J")
+
+ # It was not changed because the mapping was private:
+ file.seek(0)
+ assert_equal "Hello World", file.read
+ ensure
+ buffer&.free
+ end
end
end
end