From 6abdf051d3d91d05f262d2dfe98e1c768ff0b543 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Thu, 22 Apr 2010 17:22:03 -0700 Subject: [PATCH] Unhandled 'error' events kill program By default 'error' throws. addListener to prevent this. --- lib/events.js | 40 +++++++++++++++++++++++++++++++++ lib/http.js | 6 ++++- lib/net.js | 30 +++++++++++++++---------- src/node.js | 3 --- test/pummel/test-keep-alive.js | 6 ++--- test/pummel/test-tcp-timeout.js | 9 ++++++++ 6 files changed, 75 insertions(+), 19 deletions(-) diff --git a/lib/events.js b/lib/events.js index ed00df1e073..0ac8a691a48 100644 --- a/lib/events.js +++ b/lib/events.js @@ -1,5 +1,44 @@ exports.EventEmitter = process.EventEmitter; + +process.EventEmitter.prototype.emit = function (type) { + if (type == 'error') { + if (!this._events || !this._events.error || + (this._events.error instanceof Array && !this._events.error.length)) + { + if (arguments[1] instanceof Error) { + throw arguments[1]; + } else { + throw new Error("Uncaught, unspecfied 'error' event."); + } + return false; + } + } + + if (!this._events) return false; + if (!this._events[type]) return false; + + if (typeof this._events[type] == 'function') { + var args = Array.prototype.slice.call(arguments, 1); + + this._events[type].apply(this, args); + return true; + + } else if (this._events[type] instanceof Array) { + var args = Array.prototype.slice.call(arguments, 1); + + + var listeners = this._events[type].slice(0); + for (var i = 0, l = listeners.length; i < l; i++) { + listeners[i].apply(this, args); + } + return true; + + } else { + return false; + } +}; + // process.EventEmitter is defined in src/node_events.cc // process.EventEmitter.prototype.emit() is also defined there. process.EventEmitter.prototype.addListener = function (type, listener) { @@ -27,6 +66,7 @@ process.EventEmitter.prototype.addListener = function (type, listener) { return this; }; + process.EventEmitter.prototype.removeListener = function (type, listener) { if ('function' !== typeof listener) { throw new Error('removeListener only takes instances of Function'); diff --git a/lib/http.js b/lib/http.js index ad61baa42d0..884fd9a4d8b 100644 --- a/lib/http.js +++ b/lib/http.js @@ -548,9 +548,13 @@ function connectionListener (socket) { parser.socket = socket; if (self.secure) { - socket.setSecure(self.credentials); + socket.setSecure(self.credentials); } + socket.addListener('error', function (e) { + sys.puts('node http server: ' + e); + }); + socket.ondata = function (d, start, end) { var bytesParsed = parser.execute(d, start, end - start); if (parser.incoming && parser.incoming.upgrade) { diff --git a/lib/net.js b/lib/net.js index 205b26b80c8..247b5961c56 100644 --- a/lib/net.js +++ b/lib/net.js @@ -826,20 +826,26 @@ Stream.prototype.destroy = function (exception) { Stream.prototype._shutdown = function () { - if (this.writable) { - this.writable = false; + if (!this.writable) { + throw new Error('The connection is not writable'); + } else { + if (this.readable) { + // readable and writable + this.writable = false; - if (this.secure) { - this._shutdownSecure(); + if (this.secure) { + this._shutdownSecure(); + } + try { + shutdown(this.fd, 'write') + } catch (e) { + this.destroy(e); + return; + } + } else { + // writable but not readable + this.destroy(); } - try { - shutdown(this.fd, 'write') - } catch (e) { - this.destroy(e); - return; - } - - if (!this.readable) this.destroy(); } }; diff --git a/src/node.js b/src/node.js index 82dd7485bf2..253cf0ff7b6 100644 --- a/src/node.js +++ b/src/node.js @@ -132,8 +132,6 @@ process.__defineGetter__('stdout', function () { var net = module.requireNative('net'); stdout = new net.Stream(process.binding('stdio').stdoutFD); - stdout.addListener('error', function (err) { throw err; }); - return stdout; }); @@ -143,7 +141,6 @@ process.openStdin = function () { var net = module.requireNative('net'); var fd = process.binding('stdio').openStdin(); stdin = new net.Stream(fd); - stdin.addListener('error', function (err) { throw err; }); stdin.resume(); stdin.readable = true; return stdin; diff --git a/test/pummel/test-keep-alive.js b/test/pummel/test-keep-alive.js index cc81dfc8f17..18894a82480 100644 --- a/test/pummel/test-keep-alive.js +++ b/test/pummel/test-keep-alive.js @@ -5,9 +5,9 @@ exec = require("child_process").exec; body = "hello world\n"; server = http.createServer(function (req, res) { - res.writeHead(200, { - "Content-Length": body.length, - "Content-Type": "text/plain", + res.writeHead(200, { + "Content-Length": body.length, + "Content-Type": "text/plain" }); res.write(body); res.end(); diff --git a/test/pummel/test-tcp-timeout.js b/test/pummel/test-tcp-timeout.js index 4279daf5ce6..1b1fc0ca87f 100644 --- a/test/pummel/test-tcp-timeout.js +++ b/test/pummel/test-tcp-timeout.js @@ -5,6 +5,8 @@ starttime = null; timeouttime = null; timeout = 1000; +gotError = false + var echo_server = net.createServer(function (socket) { socket.setTimeout(timeout); @@ -14,6 +16,11 @@ var echo_server = net.createServer(function (socket) { p(timeouttime); }); + socket.addListener("error", function (e) { + assert.ok(e instanceof Error); + gotError = true; + }) + socket.addListener("data", function (d) { puts(d); socket.write(d); @@ -77,4 +84,6 @@ process.addListener("exit", function () { // Allow for 800 milliseconds more assert.ok(diff < timeout + 800); + + assert.ok(gotError); });