Fix Window private file mapping unlink EACCES issue. (#9358)

* Don't return early.

* Add missing `mapping` assignment.

* Make debug logs conditional.
This commit is contained in:
Samuel Williams 2023-12-27 00:36:56 +13:00 committed by GitHub
parent b1f67cf08e
commit e5a4f757bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 22 deletions

View File

@ -42,6 +42,8 @@ enum {
// This is used to validate the flags given by the user. // 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_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 { 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); 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"); if (!mapping) rb_sys_fail("io_buffer_map_descriptor:CreateFileMapping");
void *base = MapViewOfFile(mapping, access, (DWORD)(offset >> 32), (DWORD)(offset & 0xFFFFFFFF), size); 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->size = size;
buffer->flags = flags; buffer->flags = flags;
RB_OBJ_WRITE(self, &buffer->source, source); 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) io_buffer_free(struct rb_io_buffer *buffer)
{ {
if (buffer->base) { if (buffer->base) {
@ -247,18 +254,17 @@ io_buffer_free(struct rb_io_buffer *buffer)
buffer->size = 0; buffer->size = 0;
buffer->flags = 0; buffer->flags = 0;
buffer->source = Qnil; buffer->source = Qnil;
return 1;
} }
#if defined(_WIN32) #if defined(_WIN32)
if (buffer->mapping) { 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; buffer->mapping = NULL;
} }
#endif #endif
return 0;
} }
void void

View File

@ -521,10 +521,7 @@ class TestIOBuffer < Test::Unit::TestCase
def test_private def test_private
Tempfile.create(%w"buffer .txt") do |file| Tempfile.create(%w"buffer .txt") do |file|
file.write("Hello World") 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) buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::PRIVATE)
begin begin
assert buffer.private? assert buffer.private?
@ -538,7 +535,6 @@ class TestIOBuffer < Test::Unit::TestCase
ensure ensure
buffer&.free buffer&.free
end end
end;
end end
end end
end end