From de2d02eea70c7d4f2af8a25118adeff90b5f09ff Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Thu, 7 Nov 2024 22:30:38 +0800 Subject: [PATCH] Replace handle atomically in `IO::FileDescriptor#close` on Windows (#15165) The spec introduced in #14698 fails on Windows very rarely (e.g. https://github.com/crystal-lang/crystal/actions/runs/11681506288/job/32532033082, https://github.com/crystal-lang/crystal/actions/runs/11642959689/job/32449149741). This PR seems to fix that; other platforms already do the same in `#system_close`, and double close remains an error. --- src/crystal/system/win32/file_descriptor.cr | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/crystal/system/win32/file_descriptor.cr b/src/crystal/system/win32/file_descriptor.cr index 1f277505302a..4265701cd8b2 100644 --- a/src/crystal/system/win32/file_descriptor.cr +++ b/src/crystal/system/win32/file_descriptor.cr @@ -195,7 +195,11 @@ module Crystal::System::FileDescriptor end def file_descriptor_close(&) - if LibC.CloseHandle(windows_handle) == 0 + # Clear the @volatile_fd before actually closing it in order to + # reduce the chance of reading an outdated handle value + handle = LibC::HANDLE.new(@volatile_fd.swap(LibC::INVALID_HANDLE_VALUE.address)) + + if LibC.CloseHandle(handle) == 0 yield end end