Get rid of coupling for stdin
This commit is contained in:
parent
f2212fa59d
commit
c143cba590
@ -499,8 +499,11 @@ var FileReadStream = fs.FileReadStream = function(path, options) {
|
|||||||
this[key] = options[key];
|
this[key] = options[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
if (this.fd !== null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
fs.open(this.path, this.flags, this.mode, function(err, fd) {
|
fs.open(this.path, this.flags, this.mode, function(err, fd) {
|
||||||
if (err) {
|
if (err) {
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
|
17
src/node.js
17
src/node.js
@ -147,11 +147,20 @@ process.__defineGetter__('stdout', function () {
|
|||||||
var stdin;
|
var stdin;
|
||||||
process.openStdin = function () {
|
process.openStdin = function () {
|
||||||
if (stdin) return stdin;
|
if (stdin) return stdin;
|
||||||
var net = module.requireNative('net');
|
|
||||||
var fd = process.binding('stdio').openStdin();
|
var net = module.requireNative('net')
|
||||||
stdin = new net.Stream(fd);
|
, fs = module.requireNative('fs')
|
||||||
|
, fd = process.binding('stdio').openStdin();
|
||||||
|
|
||||||
|
if (process.binding('stdio').isStdinBlocking()) {
|
||||||
|
stdin = new net.Stream(fd);
|
||||||
|
stdin.readable = true;
|
||||||
|
} else {
|
||||||
|
stdin = new fs.FileReadStream(null, {fd: fd});
|
||||||
|
}
|
||||||
|
|
||||||
stdin.resume();
|
stdin.resume();
|
||||||
stdin.readable = true;
|
|
||||||
return stdin;
|
return stdin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include <node_stdio.h>
|
#include <node_stdio.h>
|
||||||
#include <node_events.h>
|
#include <node_events.h>
|
||||||
#include <coupling.h>
|
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -11,8 +10,6 @@ using namespace v8;
|
|||||||
namespace node {
|
namespace node {
|
||||||
|
|
||||||
|
|
||||||
static struct coupling *stdin_coupling = NULL;
|
|
||||||
|
|
||||||
static int stdin_fd = -1;
|
static int stdin_fd = -1;
|
||||||
static int stdout_fd = -1;
|
static int stdout_fd = -1;
|
||||||
|
|
||||||
@ -56,30 +53,33 @@ static Handle<Value> OpenStdin(const Arguments& args) {
|
|||||||
return ThrowException(Exception::Error(String::New("stdin already open")));
|
return ThrowException(Exception::Error(String::New("stdin already open")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stdin_fd = STDIN_FILENO;
|
||||||
if (isatty(STDIN_FILENO)) {
|
if (isatty(STDIN_FILENO)) {
|
||||||
// XXX selecting on tty fds wont work in windows.
|
// XXX selecting on tty fds wont work in windows.
|
||||||
// Must ALWAYS make a coupling on shitty platforms.
|
// Must ALWAYS make a coupling on shitty platforms.
|
||||||
stdin_fd = STDIN_FILENO;
|
stdin_flags = fcntl(stdin_fd, F_GETFL, 0);
|
||||||
} else {
|
if (stdin_flags == -1) {
|
||||||
stdin_coupling = coupling_new_pull(STDIN_FILENO);
|
// TODO DRY
|
||||||
stdin_fd = coupling_nonblocking_fd(stdin_coupling);
|
return ThrowException(Exception::Error(String::New("fcntl error!")));
|
||||||
}
|
}
|
||||||
|
|
||||||
stdin_flags = fcntl(stdin_fd, F_GETFL, 0);
|
int r = fcntl(stdin_fd, F_SETFL, stdin_flags | O_NONBLOCK);
|
||||||
if (stdin_flags == -1) {
|
if (r == -1) {
|
||||||
// TODO DRY
|
// TODO DRY
|
||||||
return ThrowException(Exception::Error(String::New("fcntl error!")));
|
return ThrowException(Exception::Error(String::New("fcntl error!")));
|
||||||
}
|
}
|
||||||
|
|
||||||
int r = fcntl(stdin_fd, F_SETFL, stdin_flags | O_NONBLOCK);
|
|
||||||
if (r == -1) {
|
|
||||||
// TODO DRY
|
|
||||||
return ThrowException(Exception::Error(String::New("fcntl error!")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return scope.Close(Integer::New(stdin_fd));
|
return scope.Close(Integer::New(stdin_fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Handle<Value>
|
||||||
|
IsStdinBlocking (const Arguments& args)
|
||||||
|
{
|
||||||
|
HandleScope scope;
|
||||||
|
return scope.Close(Boolean::New(isatty(STDIN_FILENO)));
|
||||||
|
}
|
||||||
|
|
||||||
static Handle<Value>
|
static Handle<Value>
|
||||||
IsStdoutBlocking (const Arguments& args)
|
IsStdoutBlocking (const Arguments& args)
|
||||||
{
|
{
|
||||||
@ -122,6 +122,7 @@ void Stdio::Initialize(v8::Handle<v8::Object> target) {
|
|||||||
NODE_SET_METHOD(target, "writeError", WriteError);
|
NODE_SET_METHOD(target, "writeError", WriteError);
|
||||||
NODE_SET_METHOD(target, "openStdin", OpenStdin);
|
NODE_SET_METHOD(target, "openStdin", OpenStdin);
|
||||||
NODE_SET_METHOD(target, "isStdoutBlocking", IsStdoutBlocking);
|
NODE_SET_METHOD(target, "isStdoutBlocking", IsStdoutBlocking);
|
||||||
|
NODE_SET_METHOD(target, "isStdinBlocking", IsStdinBlocking);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
26
test/simple/test-stdin-from-file.js
Normal file
26
test/simple/test-stdin-from-file.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
require('../common');
|
||||||
|
var TEST_STR = "abc\n123\nhello world\nsomething else"
|
||||||
|
, path = require('path')
|
||||||
|
, childProccess = require('child_process')
|
||||||
|
, fs = require('fs')
|
||||||
|
, stdoutScript = path.join(fixturesDir, 'echo.js')
|
||||||
|
, tmpFile = path.join(fixturesDir, 'stdin.txt')
|
||||||
|
, cmd = process.argv[0] + ' ' + stdoutScript + ' < ' + tmpFile
|
||||||
|
;
|
||||||
|
|
||||||
|
puts(cmd + "\n\n");
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(tmpFile);
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
fs.writeFileSync(tmpFile, TEST_STR);
|
||||||
|
|
||||||
|
childProccess.exec(cmd, function(err, stdout, stderr) {
|
||||||
|
fs.unlinkSync(tmpFile);
|
||||||
|
|
||||||
|
if (err) throw err;
|
||||||
|
puts(stdout);
|
||||||
|
assert.equal(stdout, "hello world\r\n" + TEST_STR);
|
||||||
|
assert.equal("", stderr);
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user