17

How can I signal EOF to a stream without closing the stream?

I've got a script that waits for input on stdin, then when I push ctrl-d, it spits output to stdout, then waits again for stdin until I press ctrl-d.

In my nodejs script, I want to spawn that script, write to the stdin stream, then somehow signal EOF without closing the stream. This doesn't work:

var http = require('http'),
    spawn = require('child_process').spawn;

var child = spawn('my_child_process');
child.stdout.on('data', function(data) {
    console.log(data.toString());
});

child.stdout.on('close', function() {
    console.log('closed');
})

http.createServer(function (req, res) {
    child.stdin.write('hello child\n');
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');

But if I change child.stdin.write(...) to child.stdin.end(...), it works, but only once; the stream is closed after that. I read somewhere that EOF isn't actually a character, it's just anything that's NOT a character, usually -1, so I tried this, but this didn't work either:

var EOF = new Buffer(1); EOF[0] = -1;
child.stdin.write("hello child\n");
child.stdin.write(EOF);
Trevor Dixon
  • 23,216
  • 12
  • 72
  • 109
  • I'm pretty sure this is not possible. See http://stackoverflow.com/questions/9633577/send-a-eof-in-a-pipe-without-closing-it – Nick White Jun 01 '12 at 00:23
  • Why can't you just close the input stream? I'm rather confused here. – jcolebrand Jun 01 '12 at 00:25
  • 1
    Because I want to write again to stdin. The process waits for EOF, then chunks on the input, then reopens /dev/stdin to wait for more. – Trevor Dixon Jun 01 '12 at 00:26
  • 3
    That seems horribly against the concept of unix, who wrote the other process? – jcolebrand Jun 01 '12 at 00:29
  • 1
    I wrote it. It's a PhantomJS script. Looks like I may have to rework that. It's not unprecedented though; coders in Python, C, C++, and probably others have wondered the same thing. – Trevor Dixon Jun 01 '12 at 00:38
  • You can change the EOL character for the life of your program to help you test: http://nodejs.org/api/os.html#os_os_eol – EhevuTov Aug 01 '13 at 00:06

3 Answers3

6

Have you tried child.stdin.write("\x04");? This is the ascii code for Ctrl+D.

cjohn
  • 11,370
  • 3
  • 30
  • 17
  • Is this cross-platform? Would that work on Windows also? – Ingwie Phoenix Nov 02 '14 at 22:51
  • I'm not sure. The question and answer predate node.js support on Windows; I have never run node.js in a Windows environment. Is `Ctrl+D` a signal in Windows? – cjohn Nov 04 '14 at 20:00
3

You did it with res just two lines below...

  • stream.write(data) is used when you, want to continue writing
  • stream.end([data]) is used when you don't need to send more data (it will close the stream)
var http = require('http'),
    spawn = require('child_process').spawn;

var child = spawn('my_child_process');
child.stdout.on('data', function(data) {
    console.log(data.toString());
});

child.stdout.on('close', function() {
    console.log('closed');
})

http.createServer(function (req, res) {
    child.stdin.end('hello child\n');
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
Kevin Sandow
  • 4,003
  • 1
  • 20
  • 33
1
var os = require("os");    
child.stdin.write("hello child\n");
child.stdin.write(os.EOL);

I use this in my project and it works

Eli
  • 99
  • 1
  • 8