Bug #12033

WSASocket can't work with Ruby extensions.

Added by nicolasnoble (Nicolas Noble) over 4 years ago. Updated 10 months ago.

Target version:
ruby -v:
ruby 2.2.3p173 (2015-08-18 revision 51636) [x64-mingw32]


Basically, when creating a gem with C code that tries to do a WSASocket() call, the socket will end up being non-viable. I have tried this using the native DevKit compiler, rake-compiler-dock, ruby 2.2, 2.1, 32 and 64 bits, to no avail. If a C extension calls into socket(), that socket will work, but if it calls into WSASocket(), it somehow won't.

I have attached an example of a very simple gem, which is basically the sample code from

In the first test, calling into socket() and binding that socket to localhost will work. In the second test, calling into WSASocket() will return a socket, but then binding it won't work, with a WSAENOTSOCK error.

If you add a main() function that simply calls into the Init_foobar() function, and compile it into a normal exe file, both tests will work normally.

My guess is that the ruby environment is doing something... weird ? And as a result, the winsock system is altered in a way that makes WSASocket unviable.

Files (2.68 KB) nicolasnoble (Nicolas Noble), 01/29/2016 10:32 AM

Updated by nicolasnoble (Nicolas Noble) over 4 years ago

I forgot to mention that I tried this under windows 10 and Windows 7, with the same result on both os.

Updated by usa (Usaku NAKAMURA) over 4 years ago

First, You don't have to care about initializing/cleanup WinSock.
Ruby does them.

To keep source level compatibility with Unix-like platforms,
Ruby makes some hack about Windows' socket.
The return value of Unix's socket is a file descriptor.
Therefore Ruby on Windows replaces WinSock's socket to return a file descriptor
instead of to return a SOCKET.
Same as socket, bind is also replaced by Ruby to accept a file descriptor instead of

But Ruby does not replace WSASocket because it doesn't exist on Unix.
So, WSASocket returns a SOCKET, and bind doesn't accept it because it's not a file descriptor.

If you really want to use WSASocket and bind in your extension, you can use
rb_w32_wrap_io_handle and rb_w32_unwrap_io_handle API.
But, anyway, you have to read and learn the implementation of Ruby on Windows :-P

Updated by nicolasnoble (Nicolas Noble) over 4 years ago

Okay. I see.

What you're telling me is that you're basically overriding at link time the list of posix-looking functions, to hijack them into "real" posix versions. Now the problem is, if I am trying to write a Ruby wrapper for a statically compiled third party library, then the link time of the extension is basically clobbering perfectly valid WSA code that has nothing to do with Ruby in the first place. See, I would believe that the right approach for what you tried to do was to do something at compilation time, using a "ruby-socket" header compatibility layer of some sorts, instead of clobbering everything at link time. Because now, it means it's impossible to bring in a static library into Ruby which contains WSA code.

Mind you, what I am trying to do is something very very typical: a thin piece of C code as a Ruby extension which wraps a third_party library. That third party library happens to do socket stuff internally, and doesn't surface them up. So to the user of that library, there's not even any WSA coding involved. But by trying to bring that extension to Ruby, you're basically mangling it as a side-effect, and effectively destroying it. That's... very unprecedented.

Thanks to your update, and a bit of googleing, I managed to find that blog post here: which perfectly explains the issue I am facing. It doesn't seem that this person found a proper way to solve that issue. Isn't there any option anywhere to avoid that ? Because, seriously, it really isn't ideal, to put it mildly.


Updated by jeremyevans0 (Jeremy Evans) 10 months ago

  • Status changed from Open to Closed

Also available in: Atom PDF