node icon indicating copy to clipboard operation
node copied to clipboard

Document `[sub]process.channel.refCounted()` and `[sub]process.channel.unrefCounted()`

Open ehmicky opened this issue 9 months ago • 0 comments

What is the problem this feature will solve?

Background

When using Node.js IPC, if the child process sets a listener on the message or disconnect events, the child process is kept alive as long as those listeners exist. This is good and done automatically by Node.js using newListener and removeListener hooks.

https://github.com/nodejs/node/blob/c137d6eb31013f2785db7bcff66bdb8a68799e2b/lib/child_process.js#L180-L185

Users can opt out of this if they want to manually manage this instead, by calling process.channel.ref() and process.channel.unref(). When they do, the automatic reference counting stops happening.

https://github.com/nodejs/node/blob/f05baff6ade84d9e7f66c9d3f425c117dc161756/lib/internal/child_process.js#L547-L572

Problem

I am contributing to a library (Execa) that has a higher-level API built on top of Node.js builtin IPC. For several reasons, I need to proxy IPC messages. To do this, I need to listen to message events. However, that listener should not keep the process alive.

The solution to this problem is currently to call process.channel.unref(). However, this has the following undesirable side effect: if the library's user is also setting up their own message/disconnect event handlers, those will not be automatically reference counted anymore. Which means the child process might accidentally exit too early.

What is the feature you are proposing to solve the problem?

A better solution to this problem is, after setting up message event listeners that should not be ref'd, to call process.channel.unrefCounted() instead (not process.channel.unref()). This has the same desired effect of preventing the child process from being kept alive. But it does not impede on automatic reference counting.

.refCounted() and .unrefCounted() have been added 5 years ago in https://github.com/nodejs/node/pull/30165. They are stable and could be useful for other use cases that the one described above.

My suggestion is: those two methods should be documented. Both for the parent process and the child process. Please note that subprocess.channel.ref(), subprocess.channel.unref(), process.channel.ref() and process.channel.unref() are already documented, so this would effectively document "sibling" methods.

ehmicky avatar May 23 '24 23:05 ehmicky