Skip to content

Commit eef0715

Browse files
committed
tls_wrap: fix interleaving in InvokeQueued
WriteItem callback may add new item to the `pending_write_items`. Ensure that this item won't be called in the same `InvokeQueued` call, as it may result in way-to-early `finish` event on js-side. fix #7733 Signed-off-by: Fedor Indutny <[email protected]>
1 parent ca55037 commit eef0715

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

src/tls_wrap.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,11 @@ bool TLSCallbacks::InvokeQueued(int status) {
141141
return false;
142142

143143
// Process old queue
144-
while (!QUEUE_EMPTY(&pending_write_items_)) {
145-
QUEUE* q = QUEUE_HEAD(&pending_write_items_);
144+
QUEUE queue;
145+
QUEUE* q = QUEUE_HEAD(&pending_write_items_);
146+
QUEUE_SPLIT(&pending_write_items_, q, &queue);
147+
while (QUEUE_EMPTY(&queue) == false) {
148+
q = QUEUE_HEAD(&queue);
146149
QUEUE_REMOVE(q);
147150

148151
WriteItem* wi = ContainerOf(&WriteItem::member_, q);
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
if (!process.versions.openssl) {
23+
console.error('Skipping because node compiled without OpenSSL.');
24+
process.exit(0);
25+
}
26+
27+
var assert = require('assert');
28+
var fs = require('fs');
29+
var net = require('net');
30+
var tls = require('tls');
31+
32+
var common = require('../common');
33+
34+
var received = '';
35+
var ended = 0;
36+
37+
var server = tls.createServer({
38+
key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'),
39+
cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem')
40+
}, function(c) {
41+
c._write('hello ', null, function() {
42+
c._write('world!', null, function() {
43+
c.destroy();
44+
});
45+
c._write(' gosh', null, function() {});
46+
});
47+
48+
server.close();
49+
}).listen(common.PORT, function() {
50+
var c = tls.connect(common.PORT, {
51+
rejectUnauthorized: false
52+
}, function() {
53+
c.on('data', function(chunk) {
54+
received += chunk;
55+
});
56+
c.on('end', function() {
57+
ended++;
58+
});
59+
});
60+
});
61+
62+
process.on('exit', function() {
63+
assert.equal(ended, 1);
64+
assert.equal(received, 'hello world! gosh');
65+
});

0 commit comments

Comments
 (0)