Passing a file descriptor to a subprocess

I have multiple subprocesses starting from a parent process and to aid with debugging they are set up as separate executables and I want to communicate with them via a passed socket.

I’m currently using named sockets to do this, but that requires interfacing with the file system, and it seems like just passing the file descriptor would be a more correct way to do this. The other alternative would be to use a port and the loopback address, but that seems a touch hacky.

From what I can tell if the processes were just simply forked this becomes easy since the file descriptors are still in the same memory and thus everything is fine, however since these are started from executables they don’t share the same memory. Thus I need some way to turn the arguments of the executable into a file descriptor.

The issue is that I can’t find a function that would take a string/int and return the corresponding file descriptor (apart from the openfile function which takes a file path).

Additionally I’m not sure if this is the right way to do this since if the subprocess was called by another langague/cli the string formatting would potentially not be identical thus I’d need to use a hex representation/otherwise to ensure that they are talking about the same file descriptor.

Yeah, this has been a long-standing missing function from the stdlib. You just have to use Obj.magic and hope they don’t change the representation one day. Or you could use this library, which does that for you:

Or, you could use this library:

Also, this probably doesn’t work on Windows.

2 Likes

Indeed, this will segfault on Windows. See https://github.com/ocaml/ocaml/pull/1990

2 Likes

More generally then I take that there is no standard way to distribute file descriptors between programs apart from explicit forks and then closing whichever half is required (re parallel processing kind of tasks)?

Interesting question. I understand sendmsg(2) to fall under POSIX standard, but as far as I can tell, by that standard it’s required only to complete the data transfer (and the same with recvmsg().) The standard says nothing about SCM_RIGHTS - what it means, what the platform is required to support, etc. If I’m right about that, then the functionality in question here is not supported by official standard, but only by traditional common practice among UNIX based operating systems. If a platform’s kernel design made it inconvenient to support for some reason, it could be omitted and still be 100% POSIX compliant.

(By the way, in case anyone is wondering as I did whether the received file descriptor might clobber a file descriptor already open in the receiving process - empirically, no, the kernel apparently dups the fd into the receiver’s file descriptor space, so sent 1 will be received as 3 or whatever following number is unused.)

1 Like

Be honest, your real reason is probably more because you are working under a very poor operating system.

Ok, that’s Unix.open_file (and I suspect it might even work in some non Unix-like operating system with which unlucky people have to work with).

This looks related to Unix.descr_of_in_channel and descr_of_out_channel.

I’m sorry, but I don’t understand this last part.