-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WindowsFile: Retrieve correct Win32 error codes #3337
Conversation
780f3b3
to
145be17
Compare
WindowsFile calls GetLastError via win32-api to retrieve win32 error code but the error code may be already reset by Ruby's internal code so that it can't retrive a correct error code. Sometimes it causes random unrecoverable errors when in_tail plugin tries to read a non-existent file like the following: 2021-04-14 03:15:45 +0000 [error]: #2 Fluent::Win32Error code: 158, The segment is already unlocked.: C:/path/to/log.txt Fiddle or FFI has a method to avoid this issue: * Fiddle.win32_last_error https://ruby-doc.org/stdlib-3.0.0/libdoc/fiddle/rdoc/Fiddle.html#method-c-win32_last_error * FFI::LastError.winapi_error https://www.rubydoc.info/github/ffi/ffi/FFI/LastError#winapi_error-instance_method We've added an equivalent method for win32-api: cosmo0920/win32-api#55 This commit replaces the retrieving the error code with this method. Signed-off-by: Takuro Ashie <ashie@clear-code.com>
145be17
to
a51ee09
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd confirmed that this patch can fix WindowsFile exceptions testing failures on Ruby 3.0 at current master(8c7d674).
At master(8c7d674):
WindowsFile exceptions:
test: ERROR_SHARING_VIOLATION raised: F
========================================================================================================================
Failure: test: ERROR_SHARING_VIOLATION raised(FileWrapperTest::WindowsFile exceptions)
./test/plugin/test_file_wrapper.rb:95:in `block (2 levels) in <class:FileWrapperTest>'
92: path = "#{TMP_DIR}/test_windows_file.txt"
93: file1 = file2 = nil
94: file1 = File.open(path, "wb")
=> 95: assert_raise(Fluent::Win32Error.new(ERROR_SHARING_VIOLATION, path)) do
96: file2 = Fluent::WindowsFile.new(path, 'r', FILE_SHARE_READ)
97: ensure
98: file2.close if file2
<#<Fluent::Win32Error: code: 32, The process cannot access the file because it is being used by another process. - ./test/plugin/../tmp/file_wrapper/test_windows_file.txt>> expected but was
<#<Fluent::Win32Error: code: 0, The operation completed successfully. - ./test/plugin/../tmp/file_wrapper/test_windows_file.txt>>
diff:
? #<Fluent::Win32Error: code: 32, The p r o c e ss cannot access the file because it is being used by another process. - ./test/plugin/../tmp/file_wrapper/test_windows_file.txt>
? 0 o e ati n ompl ted u u l
========================================================================================================================
: (0.029622)
test: Errno::ENOENT raised: F
========================================================================================================================
Failure: test: Errno::ENOENT raised(FileWrapperTest::WindowsFile exceptions)
./test/plugin/test_file_wrapper.rb:83:in `block (2 levels) in <class:FileWrapperTest>'
80: test 'Errno::ENOENT raised' do
81: path = "#{TMP_DIR}/nofile.txt"
82: file = nil
=> 83: assert_raise(Errno::ENOENT) do
84: file = Fluent::WindowsFile.new(path)
85: ensure
86: file.close if file
<Errno::ENOENT> expected but was
<#<Fluent::Win32Error: code: 0, The operation completed successfully. - ./test/plugin/../tmp/file_wrapper/nofile.txt>>
diff:
? Err no::ENOENT
? #<Fluent::Win32 or: code: 0, The operation completed successfully. - ./test/plugin/../tmp/file_wrapper/ file.txt>
========================================================================================================================
: (0.009904)
test: nothing raised: .: (0.002036)
With this patch:
WindowsFile exceptions:
test: ERROR_SHARING_VIOLATION raised: .: (0.001875)
test: Errno::ENOENT raised: .: (0.000978)
test: nothing raised:
Other testing failures are caused by weird WSAGetLastError return codes. |
@ashie I have a vague uncomfortableness with this Should not we assign some value to this variable? I felt that the variable was |
Thank you for pointing out it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside from the point above, I'm comfortable with this patch.
Which issue(s) this PR fixes:
none
What this PR does / why we need it:
WindowsFile calls GetLastError via win32-api to retrieve win32 error
code but the error code may be already reset by Ruby's internal code
so that it can't retrive a correct error code. Sometimes it causes
random unrecoverable errors when in_tail plugin tries to read a
non-existent file like the following:
Fiddle or FFI has a method to avoid this issue:
https://ruby-doc.org/stdlib-3.0.0/libdoc/fiddle/rdoc/Fiddle.html#method-c-win32_last_error
https://www.rubydoc.info/github/ffi/ffi/FFI/LastError#winapi_error-instance_method
We've added an equivalent method for win32-api:
This commit replaces the retrieving the error code with this method.
Docs Changes:
none
Release Note:
Same with the title.