From 33d6a3fcb7347db03aa12880ef521ad9dd3ca0ed Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 21 Feb 2019 23:12:01 +0100 Subject: [PATCH] src: clean up `StreamPipe` in destructor In the presence of Workers, it is not safe to assume that `StreamPipe::Unpipe()` has been called at the time when the object is destroyed. Instead, clean up when the destructor is called. PR-URL: https://github.com/nodejs/node/pull/26256 Reviewed-By: Joyee Cheung --- src/stream_pipe.cc | 2 +- ...orker-terminate-http2-respond-with-file.js | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-worker-terminate-http2-respond-with-file.js diff --git a/src/stream_pipe.cc b/src/stream_pipe.cc index 4c9b447a61c826..1a9d34b133bf0c 100644 --- a/src/stream_pipe.cc +++ b/src/stream_pipe.cc @@ -42,7 +42,7 @@ StreamPipe::StreamPipe(StreamBase* source, } StreamPipe::~StreamPipe() { - CHECK(is_closed_); + Unpipe(); } StreamBase* StreamPipe::source() { diff --git a/test/parallel/test-worker-terminate-http2-respond-with-file.js b/test/parallel/test-worker-terminate-http2-respond-with-file.js new file mode 100644 index 00000000000000..80b58ddfc5bac0 --- /dev/null +++ b/test/parallel/test-worker-terminate-http2-respond-with-file.js @@ -0,0 +1,39 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const assert = require('assert'); +const http2 = require('http2'); +const makeDuplexPair = require('../common/duplexpair'); +const { Worker, isMainThread } = require('worker_threads'); + +// This is a variant of test-http2-generic-streams-sendfile for checking +// that Workers can be terminated during a .respondWithFile() operation. + +if (isMainThread) { + return new Worker(__filename); +} + +{ + const server = http2.createServer(); + server.on('stream', common.mustCall((stream, headers) => { + stream.respondWithFile(process.execPath); // Use a large-ish file. + })); + + const { clientSide, serverSide } = makeDuplexPair(); + server.emit('connection', serverSide); + + const client = http2.connect('http://localhost:80', { + createConnection: common.mustCall(() => clientSide) + }); + + const req = client.request(); + + req.on('response', common.mustCall((headers) => { + assert.strictEqual(headers[':status'], 200); + })); + + req.on('data', common.mustCall(process.exit)); + req.on('end', common.mustNotCall()); + req.end(); +}