stdio: Do not read from stdout/err
authorisaacs <i@izs.me>
Fri, 21 Dec 2012 02:08:40 +0000 (02:08 +0000)
committerisaacs <i@izs.me>
Fri, 21 Dec 2012 19:05:46 +0000 (11:05 -0800)
This fixes windows stdio pipes in streams2 land.

lib/net.js
lib/tty.js
src/node.js
test/simple/test-stdout-stderr-reading.js [new file with mode: 0644]

index a3ddf84..10c76ff 100644 (file)
@@ -141,10 +141,13 @@ function Socket(options) {
     this._handle = options.handle; // private
   } else if (typeof options.fd === 'undefined') {
     this._handle = options && options.handle; // private
+    this.readable = options.readable !== false;
+    this.writable = options.writable !== false;
   } else {
     this._handle = createPipe();
     this._handle.open(options.fd);
-    this.readable = this.writable = true;
+    this.readable = options.readable !== false;
+    this.writable = options.writable !== false;
   }
 
   this.onend = null;
@@ -167,7 +170,7 @@ function Socket(options) {
 
   // if we have a handle, then start the flow of data into the
   // buffer.  if not, then this will happen when we connect
-  if (this._handle && (!options || options.readable !== false))
+  if (this._handle && options.readable !== false)
     this.read(0);
 }
 util.inherits(Socket, stream.Duplex);
index 5b4036d..4ba2768 100644 (file)
@@ -47,21 +47,15 @@ function ReadStream(fd, options) {
   options = util._extend({
     highWaterMark: 0,
     lowWaterMark: 0,
+    readable: true,
+    writable: false,
     handle: new TTY(fd, true)
   }, options);
 
   net.Socket.call(this, options);
 
-  this.readable = true;
-  this.writable = false;
   this.isRaw = false;
   this.isTTY = true;
-
-  // this.read = function(orig) { return function(n) {
-  //   var ret = orig.apply(this, arguments);
-  //   console.trace('TTY read(' + n + ') -> ' + ret);
-  //   return ret;
-  // } }(this.read);
 }
 inherits(ReadStream, net.Socket);
 
@@ -83,9 +77,6 @@ function WriteStream(fd) {
     writable: true
   });
 
-  this.readable = false;
-  this.writable = true;
-
   var winSize = this._handle.getWindowSize();
   if (winSize) {
     this.columns = winSize[0];
index 76c94b7..6cce75f 100644 (file)
 
       case 'PIPE':
         var net = NativeModule.require('net');
-        stream = new net.Stream(fd);
+        stream = new net.Socket({
+          fd: fd,
+          readable: false,
+          writable: true
+        });
 
-        // FIXME Should probably have an option in net.Stream to create a
+        // FIXME Should probably have an option in net.Socket to create a
         // stream from an existing fd which is writable only. But for now
         // we'll just add this hack and set the `readable` member to false.
         // Test: ./node test/fixtures/echo.js < /etc/passwd
         stream.readable = false;
+        stream.read = null;
         stream._type = 'pipe';
 
         // FIXME Hack to have stream not keep the event loop alive.
           var tty = NativeModule.require('tty');
           stdin = new tty.ReadStream(fd, {
             highWaterMark: 0,
-            lowWaterMark: 0
+            lowWaterMark: 0,
+            readable: true,
+            writable: false
           });
           break;
 
 
         case 'PIPE':
           var net = NativeModule.require('net');
-          stdin = new net.Stream({ fd: fd });
-          stdin.readable = true;
+          stdin = new net.Socket({
+            fd: fd,
+            readable: true,
+            writable: false
+          });
           break;
 
         default:
diff --git a/test/simple/test-stdout-stderr-reading.js b/test/simple/test-stdout-stderr-reading.js
new file mode 100644 (file)
index 0000000..5b67a0d
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+
+// verify that stdout is never read from.
+var net = require('net');
+var read = net.Socket.prototype.read;
+
+net.Socket.prototype.read = function() {
+  if (this.fd === 1)
+    throw new Error('reading from stdout!');
+  if (this.fd === 2)
+    throw new Error('reading from stderr!');
+  return read.apply(this, arguments);
+};
+
+if (process.argv[2] === 'child')
+  child();
+else
+  parent();
+
+function parent() {
+  var spawn = require('child_process').spawn;
+  var node = process.execPath;
+  var closes = 0;
+
+  var c1 = spawn(node, [__filename, 'child']);
+  var c1out = '';
+  c1.stdout.setEncoding('utf8');
+  c1.stdout.on('data', function(chunk) {
+    c1out += chunk;
+  });
+  c1.stderr.setEncoding('utf8');
+  c1.stderr.on('data', function(chunk) {
+    console.error('c1err: ' + chunk.split('\n').join('\nc1err: '));
+  });
+  c1.on('close', function(code, signal) {
+    closes++;
+    assert(!code);
+    assert(!signal);
+    assert.equal(c1out, 'ok\n');
+    console.log('ok');
+  });
+
+  var c2 = spawn(node, ['-e', 'console.log("ok")']);
+  var c2out = '';
+  c2.stdout.setEncoding('utf8');
+  c2.stdout.on('data', function(chunk) {
+    c2out += chunk;
+  });
+  c1.stderr.setEncoding('utf8');
+  c1.stderr.on('data', function(chunk) {
+    console.error('c1err: ' + chunk.split('\n').join('\nc1err: '));
+  });
+  c2.on('close', function(code, signal) {
+    closes++;
+    assert(!code);
+    assert(!signal);
+    assert.equal(c2out, 'ok\n');
+    console.log('ok');
+  });
+
+  process.on('exit', function() {
+    assert.equal(closes, 2, 'saw both closes');
+  });
+}
+
+function child() {
+  // should not be reading *ever* in here.
+  net.Socket.prototype.read = function() {
+    throw new Error('no reading allowed in child');
+  };
+  console.log('ok');
+}