Skip to content
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

Merged
merged 1 commit into from Apr 20, 2021

Conversation

ashie
Copy link
Member

@ashie ashie commented Apr 19, 2021

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:

  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:

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.

@ashie ashie force-pushed the fix-incorrect-win32-last-error branch from 780f3b3 to 145be17 Compare April 19, 2021 06:56
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>
@ashie ashie force-pushed the fix-incorrect-win32-last-error branch from 145be17 to a51ee09 Compare April 19, 2021 07:20
@ashie ashie marked this pull request as ready for review April 19, 2021 09:00
@ashie ashie requested a review from cosmo0920 April 19, 2021 09:00
Copy link
Contributor

@cosmo0920 cosmo0920 left a 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:

@cosmo0920
Copy link
Contributor

Other testing failures are caused by weird WSAGetLastError return codes.
We can merge this PR into master, I think. 👍

@fujimotos
Copy link
Member

fujimotos commented Apr 20, 2021

@ashie I have a vague uncomfortableness with this id_thread_data:

https://github.com/cosmo0920/win32-api/pull/55/files#diff-9a529c17bd767f1c607585ebc12ef9daaf94babeeb30a33ea6ff93f372f6dd58R70

Should not we assign some value to this variable? I felt that the variable was
waiting some initialization, but we forgot to do that.

@ashie
Copy link
Member Author

ashie commented Apr 20, 2021

Should not we assign some value to this variable? I felt that the variable was
waiting some initialization, but we didn't

Thank you for pointing out it.
I also worried about it after merging it, so I checked it.
Data_Make_Struct() calls xcalloc() so that it will be initialized by 0.
But I think it should be initialized manually to clarify the initial value.
In addition I have another worry thing, INT2NUM won't be suitable because DWORD is unsigned long.
I'll fix them and send another PR.

Copy link
Member

@fujimotos fujimotos left a 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.

@ashie ashie merged commit a47183f into fluent:master Apr 20, 2021
@ashie ashie deleted the fix-incorrect-win32-last-error branch April 20, 2021 09:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants