Bug #17813


rb_funcall() may reset the latest socket error unexpectedlly since Ruby 3.0.0

Added by kenhys (Kentaro Hayashi) about 2 years ago. Updated about 1 year ago.

Target version:
ruby -v:
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x64-mingw32]


The problem

It seems that when rb_funcall() is called, the socket error is reset.
This behavior is introduced since Ruby 3.0.0 on Windows.

With this incompatible change, it fails to get WSAGetLastError correctly
even though the previous funciton call fails.

Does it intentional change?

The actual situation

This incompatible behavior is found with the following Fiddle example.

module WinSock
  require 'fiddle/import'
  extend Fiddle::Importer
  dlload 'ws2_32.dll'
  extern 'int bind(int, void *, int)'
  extern 'int WSAGetLastError(void)'

p WinSock.bind(0, nil, 0)
p WinSock.WSAGetLastError

With Ruby 3.0 (ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x64-mingw32]),
WinSock.bind(0, nil, 0) should be failed, thus it returns -1. (expected)
WinSock.WSAGetLastError should return 10038 (WSAENOTSOCK) in this case, but returns 0. (unexpected)

With Ruby 2.7 (ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x64-mingw32]),
WinSock.bind(0, nil, 0) returns -1, (expected)
WinSock.WSAGetLastError return 10038 (WSAENOTSOCK). (expected)

Thus, the use case such as checking bind result and report socket
related error via (WSAGetLastError) doesn't work as expected with Ruby
3.0 (Windows).

The expected status

If this change is introduced by intendedly, no need to change ruby itself.
If not, it may be better to be fixed.

Additional Information

I've reported this issue to Fiddle, then since Fiddle 1.0.8,
Fiddle.win32_last_socket_error is implemented as a workaround.

Unexpected error code with WSAGetLastError even though the previous function calll was failed

Updated by usa (Usaku NAKAMURA) over 1 year ago

Ruby cannot guarantee that the state of WSA does not change between two method calls, because select is called internally when thread switch occurs.
So, the solution of fiddle (adding Fiddle.win32_last_socket_error) is unavoidable in this case, I guess.

Aaron, the maintainer of Ruby's fiddle, can you backport fiddle from upstream?

Updated by mame (Yusuke Endoh) about 1 year ago

  • Status changed from Open to Closed

This ticket was created to confirm whether this is a bug of Ruby (, and @usa (Usaku NAKAMURA) answered that it was not. And the fix in fiddle has been already backported to ruby/ruby 71d4a493b890a21fdf3b302849d6d60c11ba1d9e. I believe there is nothing to do in this ticket. Closing.


Also available in: Atom PDF