Piping file descriptors beyond std{io,out,err} to child process

I'm trying to communicate with worker process that uses file descriptors 3..6 for data transfer.

I have been able to hook into Command using command.pre_exec() to create those file descriptors, but something isn't quite working right and with https://github.com/rust-lang/rfcs/pull/2939 not moving much there is no nice API and in general very little information (and I'd prefer to not going as low as https://fraserblog.codewise.org/rust-and-file-descriptors/ does with forking the process myself.

At this moment I have a process starting, but libuv-based code inside worker errors out with uv_read_start() failed: socket is not connected.

Here is the relevant code I have so far: https://github.com/nazar-pc/mediasoup/blob/3070625a1bbcf52539790c3446881325ed020131/rust/src/worker/channels.rs#L120-L161

Any ideas or suggestions greatly appreciated!

I'm not sure but probably you need to clear "close on exec" flag for these descriptors.

Thanks for suggestion! It didn't help, but forced me to read and explore more.

I have changed code since I think there were other issues and with current version I get uv_write(): broken pipe, code: https://github.com/nazar-pc/mediasoup/blob/9e8f0c400c82f23b3864d85f5eed211c9fe64eaf/rust/src/worker/channels.rs#L118-L196

Which actually makes sense, since both FDs returned by nix::unistd::pipe() have these flags set on them: O_LARGEFILE | O_RDONLY.

The interesting thing is that even when I try to set flags on write FD with to O_LARGEFILE | O_WRONLY or just O_WRONLY, operation doesn't error, but also doesn't have any effect, which is extremely confusing.

I think this is the only thing that still needs to be fixed and it will work and I can finally move on to something more interesting.

UPD: Turns out those flags can't be changed with fcntl()...

Maybe create a minimal example which reproduces the problem so we could try it.

It is hard to do since I need to have worker binary to run it.

You can reproduce with this:

git clone https://github.com/nazar-pc/mediasoup.git
cd mediasoup
git checkout rust
npm i
cd rust
RUST_LOG=mediasoup=debug cargo test worker_manager::tests::worker_manager_test -- --nocapture

It will print this:

[2020-08-31T22:03:29Z DEBUG mediasoup::worker] new()
[2020-08-31T22:03:29Z DEBUG mediasoup::worker] spawning worker process: ../worker/out/Release/mediasoup-worker --logLevel=error --rtcMinPort=10000 --rtcMaxPort=59999
(stderr) UnixStreamSocket::Write() | uv_try_write() failed, trying uv_write(): broken pipe
(stderr) UnixStreamSocket::OnUvWriteError() | write error, closing the pipe: broken pipe

You would only probably need to tweak rust/src/worker/channels.rs.

Turned out to be a bug in the library that got fixed quickly: https://github.com/stjepang/async-fs/issues/4