I am writing a multiprocess socket server, and on Linux it works perfectly, but on Windows it just crashes without any error. I believe it is because it does not actually inherit the socket file descriptor correctly.
Below is a stripped down version of my code that just prints all the file descriptors in the child process. On my windows VM it prints a list of FDs, but the FD that it gets passed from the parent process is not in the list, it's higher than any of the listed ones.
I found this windows documentation about how to inherit a socket: https://docs.microsoft.com/en-us/windows/win32/sysinfo/handle-inheritance
I also found that Boost.Process has this property, that suggests by default handlers are inherited: https://www.boost.org/doc/libs/1_78_0/doc/html/boost/process/limit_handles.html
But It's not clear why my socket isn't getting inherited, and what to do about it.
#include <stdio.h>
#include <string>
#include <boost/asio.hpp>
#include <boost/process.hpp>
#include <boost/process/handles.hpp>
using boost::this_process::native_handle_type;
using namespace boost::asio;
using ip::tcp;
int main(int argc, char const *argv[])
{
int port = 5923;
if (argc == 2 && strcmp(argv[1], "--help")==0) {
printf("%s [port]\n", argv[0]);
return 0;
} else if (argc == 3 && strcmp(argv[1], "--child")==0) {
printf("child process\n");
int fd = std::stoi(argv[2]);
auto hds = boost::this_process::get_handles();
for (auto h : hds) {
std::cout << h << std::endl;
}
printf("got FD %d\n", fd);
return 0;
} else if (argc == 2)
{
port = std::stoi(argv[1]);
}
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v6(), port));
while (1)
{
printf("waiting for clients\n");
tcp::socket peersocket(io_service);
acceptor.accept(peersocket);
auto endpoint = peersocket.remote_endpoint();
printf("Accepted new connection from a client %s:%d\n", endpoint.address(), endpoint.port());
std::string fd = std::to_string(peersocket.release());
std::cout << fd << std::endl;
boost::process::spawn(argv[0], "--child", fd);
}
return 0;
}