From 7dd3b676b8f0207f3050831711d5e09d6783f535 Mon Sep 17 00:00:00 2001 From: Kelvin Jin Date: Wed, 3 May 2017 14:04:45 -0700 Subject: [PATCH 1/2] http2: client session destroy also destroys associated socket --- lib/internal/http2/core.js | 13 ++++++++++--- test/parallel/test-http2-create-client-connect.js | 2 +- test/parallel/test-http2-create-client-session.js | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 6afc87e6f7..3e14dc0336 100755 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -435,7 +435,16 @@ class Http2Session extends EventEmitter { destroy() { const state = this[kState]; const streams = state.streams; + const socket = this[kSocket]; + if (state.destroyed) { + return; + } state.destroyed = true; + if (!socket.destroyed) { + socket.destroy(); + } + this[kSocket] = undefined; + this[kServer] = undefined; timers.unenroll(this); streams.forEach((value, key) => { value[kSession] = undefined; @@ -955,12 +964,10 @@ Object.defineProperties(Http2Session.prototype, { // establishment of a new connection. function socketDestroy(error) { const session = this[kSession]; - session.destroy(); - session[kServer] = undefined; - session[kSocket] = undefined; this[kServer] = undefined; this.destroy = this[kDestroySocket]; this.destroy(error); + session.destroy(); } function socketOnResume() { diff --git a/test/parallel/test-http2-create-client-connect.js b/test/parallel/test-http2-create-client-connect.js index e9b394858e..5a548dcb43 100755 --- a/test/parallel/test-http2-create-client-connect.js +++ b/test/parallel/test-http2-create-client-connect.js @@ -28,7 +28,7 @@ const URL = url.URL; let count = items.length; const maybeClose = common.mustCall((client) => { - client.socket.destroy(); + client.destroy(); if (--count === 0) { setImmediate(() => server.close()); } diff --git a/test/parallel/test-http2-create-client-session.js b/test/parallel/test-http2-create-client-session.js index dd41efebad..fd2816faf8 100755 --- a/test/parallel/test-http2-create-client-session.js +++ b/test/parallel/test-http2-create-client-session.js @@ -47,7 +47,7 @@ server.on('listening', common.mustCall(function() { assert.strictEqual(body, data); if (--expected === 0) { server.close(); - client.socket.destroy(); + client.destroy(); } })); req.end(); From 9968c40cb31fcf88f2e04a3a9232a05ca61f6325 Mon Sep 17 00:00:00 2001 From: Kelvin Jin Date: Thu, 4 May 2017 10:33:51 -0700 Subject: [PATCH 2/2] http2: add test for client.destroy behavior --- test/parallel/test-http2-client-destroy.js | 48 ++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100755 test/parallel/test-http2-client-destroy.js diff --git a/test/parallel/test-http2-client-destroy.js b/test/parallel/test-http2-client-destroy.js new file mode 100755 index 0000000000..ebc94b144f --- /dev/null +++ b/test/parallel/test-http2-client-destroy.js @@ -0,0 +1,48 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const h2 = require('http2'); + +const server = h2.createServer(); +server.listen(0); + +server.on('listening', common.mustCall(function() { + const port = this.address().port; + const headers = { ':path': '/' }; + + const destroyCallbacks = [ + client => client.destroy(), + client => client.socket.destroy() + ] + + let remaining = destroyCallbacks.length; + + destroyCallbacks.forEach((destroyCallback) => { + const client = h2.connect(`http://localhost:${port}`); + client.on('connect', common.mustCall(() => { + const socket = client.socket; + + assert(client.socket, 'client session has associated socket'); + assert(!client.destroyed, + 'client has not been destroyed before destroy is called'); + assert(!socket.destroyed, + 'socket has not been destroyed before destroy is called'); + + // Ensure that 'close' event is emitted + client.on('close', common.mustCall(() => {})); + + destroyCallback(client); + + assert(!client.socket, 'client.socket undefined after destroy is called'); + assert(client.destroyed, + 'client marked as destroyed after destroy is called'); + assert(socket.destroyed, + 'socket marked as destroyed after destroy is called'); + + if (--remaining === 0) { + server.close(); + } + })); + }); +}));