Skip to content

Commit ba9e180

Browse files
committed
Refactor delete peer_close_watching_, try_catch, add kPeerCloseCallbackField
1 parent 554052d commit ba9e180

3 files changed

Lines changed: 56 additions & 58 deletions

File tree

lib/internal/child_process.js

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ const handleConversion = {
176176
// waiting for the NODE_HANDLE_ACK of the current passing handle.
177177
assert(!target._pendingMessage);
178178
target._pendingMessage =
179-
{ callback, message, handle, options, retransmissions: 0 };
179+
{ callback, message, handle, options, retransmissions: 0 };
180180
} else {
181181
handle.close();
182182
}
@@ -335,8 +335,8 @@ function flushStdio(subprocess) {
335335
function createSocket(pipe, readable, watchPeerClose) {
336336
const sock = net.Socket({ handle: pipe, readable });
337337
if (watchPeerClose &&
338-
process.platform !== 'win32' &&
339-
typeof pipe?.watchPeerClose === 'function') {
338+
process.platform !== 'win32' &&
339+
typeof pipe?.watchPeerClose === 'function') {
340340
pipe.watchPeerClose(true, () => sock.destroy());
341341
sock.once('close', () => pipe.watchPeerClose(false));
342342
}
@@ -375,7 +375,7 @@ ChildProcess.prototype.spawn = function spawn(options) {
375375

376376

377377
validateOneOf(options.serialization, 'options.serialization',
378-
[undefined, 'json', 'advanced']);
378+
[undefined, 'json', 'advanced']);
379379
const serialization = options.serialization || 'json';
380380

381381
if (ipc !== undefined) {
@@ -387,7 +387,7 @@ ChildProcess.prototype.spawn = function spawn(options) {
387387

388388
ArrayPrototypePush(options.envPairs, `NODE_CHANNEL_FD=${ipcFd}`);
389389
ArrayPrototypePush(options.envPairs,
390-
`NODE_CHANNEL_SERIALIZATION_MODE=${serialization}`);
390+
`NODE_CHANNEL_SERIALIZATION_MODE=${serialization}`);
391391
}
392392

393393
validateString(options.file, 'options.file');
@@ -408,10 +408,10 @@ ChildProcess.prototype.spawn = function spawn(options) {
408408

409409
// Run-time errors should emit an error, not throw an exception.
410410
if (err === UV_EACCES ||
411-
err === UV_EAGAIN ||
412-
err === UV_EMFILE ||
413-
err === UV_ENFILE ||
414-
err === UV_ENOENT) {
411+
err === UV_EAGAIN ||
412+
err === UV_EMFILE ||
413+
err === UV_ENFILE ||
414+
err === UV_ENOENT) {
415415
if (childProcessSpawn.hasSubscribers) {
416416
childProcessSpawn.error.publish({
417417
process: this,
@@ -501,7 +501,7 @@ ChildProcess.prototype.spawn = function spawn(options) {
501501

502502
for (i = 0; i < stdio.length; i++)
503503
ArrayPrototypePush(this.stdio,
504-
stdio[i].socket === undefined ? null : stdio[i].socket);
504+
stdio[i].socket === undefined ? null : stdio[i].socket);
505505

506506
// Add .send() method and start listening for IPC data
507507
if (ipc !== undefined) setupChannel(this, ipc, serialization);
@@ -667,16 +667,16 @@ function setupChannel(target, channel, serializationMode) {
667667
target.on('internalMessage', function(message, handle) {
668668
// Once acknowledged - continue sending handles.
669669
if (message.cmd === 'NODE_HANDLE_ACK' ||
670-
message.cmd === 'NODE_HANDLE_NACK') {
670+
message.cmd === 'NODE_HANDLE_NACK') {
671671

672672
if (target._pendingMessage) {
673673
if (message.cmd === 'NODE_HANDLE_ACK') {
674674
closePendingHandle(target);
675675
} else if (target._pendingMessage.retransmissions++ ===
676-
MAX_HANDLE_RETRANSMISSIONS) {
676+
MAX_HANDLE_RETRANSMISSIONS) {
677677
closePendingHandle(target);
678678
process.emitWarning('Handle did not reach the receiving process ' +
679-
'correctly', 'SentHandleNotReceivedWarning');
679+
'correctly', 'SentHandleNotReceivedWarning');
680680
}
681681
}
682682

@@ -686,9 +686,9 @@ function setupChannel(target, channel, serializationMode) {
686686

687687
if (target._pendingMessage) {
688688
target._send(target._pendingMessage.message,
689-
target._pendingMessage.handle,
690-
target._pendingMessage.options,
691-
target._pendingMessage.callback);
689+
target._pendingMessage.handle,
690+
target._pendingMessage.options,
691+
target._pendingMessage.callback);
692692
}
693693

694694
for (let i = 0; i < queue.length; i++) {
@@ -785,9 +785,9 @@ function setupChannel(target, channel, serializationMode) {
785785
// will result in error message that is weakly consumable.
786786
// So perform a final check on message prior to sending.
787787
if (typeof message !== 'string' &&
788-
typeof message !== 'object' &&
789-
typeof message !== 'number' &&
790-
typeof message !== 'boolean') {
788+
typeof message !== 'object' &&
789+
typeof message !== 'number' &&
790+
typeof message !== 'boolean') {
791791
throw new ERR_INVALID_ARG_TYPE(
792792
'message', ['string', 'object', 'number', 'boolean'], message);
793793
}
@@ -848,8 +848,8 @@ function setupChannel(target, channel, serializationMode) {
848848
handle.setSimultaneousAccepts(true);
849849
}
850850
} else if (this._handleQueue &&
851-
!(message && (message.cmd === 'NODE_HANDLE_ACK' ||
852-
message.cmd === 'NODE_HANDLE_NACK'))) {
851+
!(message && (message.cmd === 'NODE_HANDLE_ACK' ||
852+
message.cmd === 'NODE_HANDLE_NACK'))) {
853853
// Queue request anyway to avoid out-of-order messages.
854854
ArrayPrototypePush(this._handleQueue, {
855855
callback: callback,
@@ -986,11 +986,11 @@ function setupChannel(target, channel, serializationMode) {
986986
const INTERNAL_PREFIX = 'NODE_';
987987
function isInternal(message) {
988988
return (message !== null &&
989-
typeof message === 'object' &&
990-
typeof message.cmd === 'string' &&
991-
message.cmd.length > INTERNAL_PREFIX.length &&
992-
StringPrototypeSlice(message.cmd, 0, INTERNAL_PREFIX.length) ===
993-
INTERNAL_PREFIX);
989+
typeof message === 'object' &&
990+
typeof message.cmd === 'string' &&
991+
message.cmd.length > INTERNAL_PREFIX.length &&
992+
StringPrototypeSlice(message.cmd, 0, INTERNAL_PREFIX.length) ===
993+
INTERNAL_PREFIX);
994994
}
995995

996996
const nop = FunctionPrototype;
@@ -1028,7 +1028,7 @@ function getValidStdio(stdio, sync) {
10281028
if (stdio === 'ignore') {
10291029
ArrayPrototypePush(acc, { type: 'ignore' });
10301030
} else if (stdio === 'pipe' || stdio === 'overlapped' ||
1031-
(typeof stdio === 'number' && stdio < 0)) {
1031+
(typeof stdio === 'number' && stdio < 0)) {
10321032
const a = {
10331033
type: stdio === 'overlapped' ? 'overlapped' : 'pipe',
10341034
readable: i === 0,
@@ -1068,7 +1068,7 @@ function getValidStdio(stdio, sync) {
10681068
fd: typeof stdio === 'number' ? stdio : stdio.fd,
10691069
});
10701070
} else if (getHandleWrapType(stdio) || getHandleWrapType(stdio.handle) ||
1071-
getHandleWrapType(stdio._handle)) {
1071+
getHandleWrapType(stdio._handle)) {
10721072
const handle = getHandleWrapType(stdio) ?
10731073
stdio :
10741074
getHandleWrapType(stdio.handle) ? stdio.handle : stdio._handle;

src/pipe_wrap.cc

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,6 @@ PipeWrap::PipeWrap(Environment* env,
162162
// Suggestion: uv_pipe_init() returns void.
163163
}
164164

165-
PipeWrap::~PipeWrap() {
166-
peer_close_watching_ = false;
167-
peer_close_cb_.Reset();
168-
}
169-
170165
void PipeWrap::Bind(const FunctionCallbackInfo<Value>& args) {
171166
PipeWrap* wrap;
172167
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This());
@@ -228,16 +223,20 @@ void PipeWrap::WatchPeerClose(const FunctionCallbackInfo<Value>& args) {
228223
CHECK_GT(args.Length(), 0);
229224
CHECK(args[0]->IsBoolean());
230225
const bool enable = args[0].As<v8::Boolean>()->Value();
226+
227+
Environment* env = wrap->env();
228+
Isolate* isolate = env->isolate();
229+
v8::HandleScope handle_scope(isolate);
230+
v8::Context::Scope context_scope(env->context());
231+
Local<Object> obj = wrap->object();
231232

232233
// UnwatchPeerClose
233234
if (!enable) {
234-
if (!wrap->peer_close_watching_) {
235-
wrap->peer_close_cb_.Reset();
235+
if (obj->GetInternalField(kPeerCloseCallbackField).As<Value>()->IsUndefined()) {
236236
return;
237237
}
238238

239-
wrap->peer_close_watching_ = false;
240-
wrap->peer_close_cb_.Reset();
239+
obj->SetInternalField(kPeerCloseCallbackField, v8::Undefined(isolate));
241240
uv_read_stop(wrap->stream());
242241
return;
243242
}
@@ -246,26 +245,21 @@ void PipeWrap::WatchPeerClose(const FunctionCallbackInfo<Value>& args) {
246245
return;
247246
}
248247

249-
if (wrap->peer_close_watching_) {
248+
if (!obj->GetInternalField(kPeerCloseCallbackField).As<Value>()->IsUndefined()) {
250249
return;
251250
}
252251

253252
CHECK_GT(args.Length(), 1);
254253
CHECK(args[1]->IsFunction());
255254

256-
Environment* env = wrap->env();
257-
Isolate* isolate = env->isolate();
258-
259-
// Store the JS callback securely so it isn't garbage collected.
260-
wrap->peer_close_cb_.Reset(isolate, args[1].As<Function>());
261-
wrap->peer_close_watching_ = true;
255+
// Store the JS callback in an internal field.
256+
obj->SetInternalField(kPeerCloseCallbackField, args[1]);
262257

263258
// Start reading to detect EOF/ECONNRESET from the peer.
264259
// We use our custom allocator and reader, ignoring actual data.
265260
int err = uv_read_start(wrap->stream(), PeerCloseAlloc, PeerCloseRead);
266261
if (err != 0) {
267-
wrap->peer_close_watching_ = false;
268-
wrap->peer_close_cb_.Reset();
262+
obj->SetInternalField(kPeerCloseCallbackField, v8::Undefined(isolate));
269263
}
270264
}
271265

@@ -282,7 +276,7 @@ void PipeWrap::PeerCloseRead(uv_stream_t* stream,
282276
ssize_t nread,
283277
const uv_buf_t* buf) {
284278
PipeWrap* wrap = static_cast<PipeWrap*>(stream->data);
285-
if (wrap == nullptr || !wrap->peer_close_watching_) return;
279+
if (wrap == nullptr) return;
286280

287281
// Ignore actual data reads or EAGAIN (0). We only watch for disconnects.
288282
if (nread > 0 || nread == 0) return;
@@ -291,22 +285,25 @@ void PipeWrap::PeerCloseRead(uv_stream_t* stream,
291285
if (nread != UV_EOF && nread != UV_ECONNRESET) return;
292286

293287
// Peer has closed the connection. Stop reading immediately.
294-
wrap->peer_close_watching_ = false;
295288
uv_read_stop(stream);
296289

297-
if (wrap->peer_close_cb_.IsEmpty()) return;
298290
Environment* env = wrap->env();
299291
Isolate* isolate = env->isolate();
300292

301293
// Set up V8 context and handles to safely execute the JS callback.
302294
v8::HandleScope handle_scope(isolate);
303295
v8::Context::Scope context_scope(env->context());
304-
Local<Function> cb = wrap->peer_close_cb_.Get(isolate);
305-
// Reset before calling to prevent re-entrancy issues
306-
wrap->peer_close_cb_.Reset();
296+
Local<Object> obj = wrap->object();
307297

308-
errors::TryCatchScope try_catch(env);
309-
try_catch.SetVerbose(true);
298+
// Check if callback is set
299+
if (obj->GetInternalField(kPeerCloseCallbackField).As<Value>()->IsUndefined()) {
300+
return;
301+
}
302+
303+
Local<Value> cb_value = obj->GetInternalField(kPeerCloseCallbackField).As<Value>();
304+
Local<Function> cb = cb_value.As<Function>();
305+
// Reset before calling to prevent re-entrancy issues
306+
obj->SetInternalField(kPeerCloseCallbackField, v8::Undefined(isolate));
310307

311308
// MakeCallback properly tracks AsyncHooks context and flushes microtasks.
312309
wrap->MakeCallback(cb, 0, nullptr);

src/pipe_wrap.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ class PipeWrap : public ConnectionWrap<PipeWrap, uv_pipe_t> {
4040
IPC
4141
};
4242

43+
enum InternalFields {
44+
kPeerCloseCallbackField = LibuvStreamWrap::kInternalFieldCount,
45+
kInternalFieldCount
46+
};
47+
4348
static v8::MaybeLocal<v8::Object> Instantiate(Environment* env,
4449
AsyncWrap* parent,
4550
SocketType type);
@@ -54,7 +59,6 @@ class PipeWrap : public ConnectionWrap<PipeWrap, uv_pipe_t> {
5459
SET_SELF_SIZE(PipeWrap)
5560

5661
private:
57-
~PipeWrap() override;
5862
PipeWrap(Environment* env,
5963
v8::Local<v8::Object> object,
6064
ProviderType provider,
@@ -78,9 +82,6 @@ class PipeWrap : public ConnectionWrap<PipeWrap, uv_pipe_t> {
7882
const v8::FunctionCallbackInfo<v8::Value>& args);
7983
#endif
8084
static void Fchmod(const v8::FunctionCallbackInfo<v8::Value>& args);
81-
82-
bool peer_close_watching_ = false;
83-
v8::Global<v8::Function> peer_close_cb_;
8485
};
8586

8687

0 commit comments

Comments
 (0)