↓ Ir para o conteúdo principal

← todas as notas

📎 Webclip

How I fixed Node.js

The post follows a first open-source contribution in node.js. The author starts from a ChildProcess memory leak, traces how spawn, read, kill, maybeClose, and flushStdio interact, and finds that calling read() on stdout sets _consuming in a way that prevents stdout from closing.

Reading notes
#

  • The bug appears when a child process is spawned, its stdout is read, and the process is killed, because ChildProcess objects are not being freed by the garbage collector.
  • The reproducing script uses weak.js to track garbage collection and shows child_processes_in_memory steadily increasing.
  • The author investigates ChildProcess.kill(), the constructor, and the onexit handler, then focuses on maybeClose and the _closesGot and _closesNeeded counters.
  • ChildProcess closes only after the shell command finishes and stdout and stderr emit close events.
  • Tracing emitted events shows that some leaking ChildProcess objects never emit close events.
  • Removing the call to p.stdout.read() makes the close events fire consistently.
  • In net.js, Socket.prototype.read sets this._consuming to true the first time it is called with a nonzero argument, and p.stdout.read() does that.
  • In flushStdio, stream.resume() is skipped when stream._consuming is set, so stdout is not resumed after exit.
  • The fix is to remove stream._consuming from the condition in flushStdio so resume() runs and the stream can close.
  • The author adds a test, changes it from yes to echo for Windows compatibility, and gets the pull request approved.