http_server: fix resume after socket close
authorFedor Indutny <fedor@indutny.com>
Fri, 11 Sep 2015 21:04:26 +0000 (14:04 -0700)
committerJeremiah Senkpiel <fishrock123@rocketmail.com>
Tue, 15 Sep 2015 01:51:15 +0000 (21:51 -0400)
Socket resume may happen on a next tick, and in following scenario:

1. `socket.resume()`
2. `socket._handle.close()`
3. `socket._handle = null;`

The `_resume` will be invoked with empty `._handle` property. There is
nothing bad about it, and we should just ignore the `resume`/`pause`
events in this case.

Same applies to the unconsuming of socket on adding `data` and/or
`readable` event listeners.

Fix: https://github.com/nodejs/node/issues/2821

PR-URL: https://github.com/nodejs/node/pull/2824
Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
lib/_http_server.js
test/parallel/test-http-regr-gh-2821.js [new file with mode: 0644]

index 16460fc..7acc108 100644 (file)
@@ -512,11 +512,13 @@ function connectionListener(socket) {
 exports._connectionListener = connectionListener;
 
 function onSocketResume() {
-  this._handle.readStart();
+  if (this._handle)
+    this._handle.readStart();
 }
 
 function onSocketPause() {
-  this._handle.readStop();
+  if (this._handle)
+    this._handle.readStop();
 }
 
 function socketOnWrap(ev, fn) {
@@ -526,7 +528,7 @@ function socketOnWrap(ev, fn) {
     return res;
   }
 
-  if (ev === 'data' || ev === 'readable')
+  if (this._handle && (ev === 'data' || ev === 'readable'))
     this.parser.unconsume(this._handle._externalStream);
 
   return res;
diff --git a/test/parallel/test-http-regr-gh-2821.js b/test/parallel/test-http-regr-gh-2821.js
new file mode 100644 (file)
index 0000000..4fdef23
--- /dev/null
@@ -0,0 +1,24 @@
+'use strict';
+const common = require('../common');
+const assert = require('assert');
+const http = require('http');
+
+const server = http.createServer(function(req, res) {
+  res.writeHead(200);
+  res.end();
+
+  server.close();
+});
+
+server.listen(common.PORT, function() {
+
+  const req = http.request({
+    method: 'POST',
+    port: common.PORT
+  });
+
+  const payload = new Buffer(16390);
+  payload.fill('Й');
+  req.write(payload);
+  req.end();
+});