Search code examples
c++boostcross-platformboost-asiounix-socket

Unix domain socket bind failed in windows


I'm running the following code in order to create listener to unix domain socket. Under macOS this code is working fine, but in Windows it produces the following error from the tcp_acceptor command : WSAEOPNOTSUPP

Here's a minimal reproducible example :

#include <iostream>
#include <boost/asio/local/stream_protocol.hpp>
constexpr char* kFileName = "file.sock";
using namespace std;
using namespace boost::asio;

int main(int argc, char* argv[])
{
    io_context my_io_context;
    ::_unlink(kFileName); // Remove previous binding.
    local::stream_protocol::endpoint server(kFileName);
    local::stream_protocol::acceptor acceptor(my_io_context, server);
    local::stream_protocol::socket socket(my_io_context);
    acceptor.accept(socket);
    return 0;
}

While debugging inside the boost library, i saw that the failure comes from the internal bind in the following code :

enter image description here

and this is the frame variables (it's clearly visible that sa_family = AF_UNIX (1):

enter image description here

I know that unix domain socket was introduced in windows10 few years ago, and i'm working with the latest version so it should be supported. Any idea what's wrong in my code?

EDIT : I've found out that in linux based machine I pass the following sockaddr to ::bind

(const boost::asio::detail::socket_addr_type) *addr = (sa_len = '\0', sa_family = '\x01', sa_data = "/tmp/server.sock")
(lldb) memory read addr
0x7ffeefbffa00: 00 01 2f 74 6d 70 2f 73 65 72 76 65 72 2e 73 6f  ../tmp/server.so
0x7ffeefbffa10: 63 6b 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ck..............```

and in windows i get a slightly different struct :

{sa_family=1 sa_data=0x000000fffd33f682 "C:\\temp\\UnixSo... }const sockaddr *

Notice that the len field is missing in the windows platform.

Thanks


Solution

  • The issue seems to be the SO_REUSEADDR socket option, which ASIO by default sets. Setting this option itself succeeds, but causes the subsequent bind to fail.

    Construct the acceptor with reuse_addr = false, then the binding should succeed:

      local::stream_protocol::acceptor acceptor(my_io_context, server, false);