dominictarr / mux-demux

mutiplex-demultiplex multiple streams through a single text Stream
MIT License
179 stars 15 forks source link

Doesn't work with child process pipes? #34

Open tlrobinson opened 9 years ago

tlrobinson commented 9 years ago

Perhaps this is a bug in my code, but I can't figure out why mux-demux works with child processes over stdin/stdout, but not a custom pipe. e.x. this works fine:

parent.js:

var MuxDemux = require("mux-demux");
var spawn = require("child_process").spawn;

var mx = MuxDemux();
var ds = mx.createWriteStream("times");
setInterval(function () { ds.write(new Date().toString()) }, 1000);

var proc = spawn("node", ["child.js"], { stdio: ["pipe", "pipe", 2] });
proc.stdout.pipe(mx).pipe(proc.stdin);

child.js:

var MuxDemux = require("mux-demux");
var net = require("net");

var mx = MuxDemux(function (stream) {
  stream.on("data", function(data) { process.stderr.write(data+"\n") });
});

process.stdin.pipe(mx).pipe(process.stdout);

However it doesn't work if you change the last 2 lines of parent.js to this:

var proc = spawn("node", ["child.js"], { stdio: [0, 1, 2, "pipe"] });
proc.stdio[3].pipe(mx).pipe(proc.stdio[3]);

and the last line of child.js to this:

var parent = new net.Socket({ fd: 3 });
parent.pipe(mx).pipe(parent);

Yet I can send and receive messages over that stream using write and on("data", ...).

dominictarr commented 9 years ago

I didn't even know you could do that! Is any data getting through at all? maybe a createStream message is being dropped? when you call mx.createWriteStream it sends a message telling it to create a stream (analogous to your telephone ringing) My guess is that regular stdio streams handle buffering different to this special stream. Try moving mx.createWriteStream() into a setTimeout and see if that works. Otherwise, intercept the output from the parent process and dump the data that is actually written to the socket, and compare that with what the child sees.

tlrobinson commented 9 years ago

Ok this is odd. If I do the following in parent.js it works fine...

proc.stdio[3].pipe(mx);
mx.on("data", function(data) { proc.stdio[3].write(data); });
dominictarr commented 9 years ago

Okay I found another hack. proc.stdio[3].writable = true and it works. hmm...

You are using this differently to regular stdio, because with that you'd write to 0 and read from 1. but here you are both reading and writing from 3. But either this is a bug in node, or you are doing it wrong. It may be that custom pipes are not ment to be used like this... I'm not sure, I didn't actually know you could do this.