node: do not ever close stdio
authorFedor Indutny <fedor.indutny@gmail.com>
Thu, 23 Jan 2014 09:35:18 +0000 (13:35 +0400)
committerFedor Indutny <fedor.indutny@gmail.com>
Thu, 30 Jan 2014 17:26:19 +0000 (21:26 +0400)
Even if stdio streams are opened as file streams, we should not ever try
to close them. This could be accomplished by passing `autoClose: false`
in options on their creation.

lib/fs.js
src/node.js
test/fixtures/echo-close-check.js [new file with mode: 0644]
test/simple/test-stdin-from-file.js

index 2cc9431..14ca77b 100644 (file)
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -1695,12 +1695,16 @@ WriteStream.prototype.destroySoon = WriteStream.prototype.end;
 
 // SyncWriteStream is internal. DO NOT USE.
 // Temporary hack for process.stdout and process.stderr when piped to files.
-function SyncWriteStream(fd) {
+function SyncWriteStream(fd, options) {
   Stream.call(this);
 
+  options = options || {};
+
   this.fd = fd;
   this.writable = true;
   this.readable = false;
+  this.autoClose = options.hasOwnProperty('autoClose') ?
+      options.autoClose : true;
 }
 
 util.inherits(SyncWriteStream, Stream);
@@ -1750,7 +1754,8 @@ SyncWriteStream.prototype.end = function(data, arg1, arg2) {
 
 
 SyncWriteStream.prototype.destroy = function() {
-  fs.closeSync(this.fd);
+  if (this.autoClose)
+    fs.closeSync(this.fd);
   this.fd = null;
   this.emit('close');
   return true;
index 375bdfa..bdbe1c5 100644 (file)
 
       case 'FILE':
         var fs = NativeModule.require('fs');
-        stream = new fs.SyncWriteStream(fd);
+        stream = new fs.SyncWriteStream(fd, { autoClose: false });
         stream._type = 'fs';
         break;
 
 
         case 'FILE':
           var fs = NativeModule.require('fs');
-          stdin = new fs.ReadStream(null, { fd: fd });
+          stdin = new fs.ReadStream(null, { fd: fd, autoClose: false });
           break;
 
         case 'PIPE':
diff --git a/test/fixtures/echo-close-check.js b/test/fixtures/echo-close-check.js
new file mode 100644 (file)
index 0000000..1681553
--- /dev/null
@@ -0,0 +1,41 @@
+// 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');
+var net = require('net');
+
+process.stdout.write('hello world\r\n');
+
+var stdin = process.openStdin();
+
+stdin.on('data', function(data) {
+  process.stdout.write(data.toString());
+});
+
+stdin.on('end', function() {
+  // If stdin's fd will be closed - createServer may get it
+  var server = net.createServer(function() {
+  }).listen(common.PORT, function() {
+    assert(typeof server._handle.fd !== 'number' || server._handle.fd > 2);
+    server.close();
+  });
+});
index 9c2ddfd..617b903 100644 (file)
@@ -28,7 +28,7 @@ var join = require('path').join;
 var childProccess = require('child_process');
 var fs = require('fs');
 
-var stdoutScript = join(common.fixturesDir, 'echo.js');
+var stdoutScript = join(common.fixturesDir, 'echo-close-check.js');
 var tmpFile = join(common.fixturesDir, 'stdin.txt');
 
 var cmd = '"' + process.argv[0] + '" "' + stdoutScript + '" < "' +