Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

win: exit event not emitted as long as a grandchild still exists #2914

Closed
eladb opened this issue Mar 12, 2012 · 1 comment
Closed

win: exit event not emitted as long as a grandchild still exists #2914

eladb opened this issue Mar 12, 2012 · 1 comment

Comments

@eladb
Copy link

eladb commented Mar 12, 2012

On Windows, if a child process spawns a grandchild and then dies leaving the grandchild alive, the exit event is not triggered on the parent process.

The exit event is not emitted because node waits for the stdio streams to be closed before emitting the exit event (in this function, _closesGot is 1 instead of 3 because only stdin is destroyed proactively).

On Unix, these streams are closed as soon as the child exits. On Windows, only when the grandchild exits, these streams are closed and the exit event is emitted on the parent.

I'm still trying to figure out exactly what is the issue but the main suspect now seems to be that the grandchild automatically inherits the named pipe handles created to stream stdio to the child, so even when the child exits, these handles are still referenced by the grandchild and therefore not closed.

This also seems related somehow to the fact that there's a console window associated with the stream chain. Any form of detached/consoless/windowless children seem to affect this behavior.

BTW, explicitly destroying stdout and stderr (as suggested in #818?) also fixes the problem but it feels like inheriting those handles is a problem anyway.

@chrisdickinson
Copy link

Looks like this is no longer an issue:

var childProcess = require('child_process')
var spawn = childProcess.spawn
var id = +(process.argv[2] || 0)

if (id > 1) {
  setInterval(function(xs) {
    // ok
    console.log('alive!', id)
  }, 10);
  return
} else {
  console.log('alive', id)
}

console.log(__filename)
var child = spawn(process.execPath, [__filename, '' + (id + 1)]).on('error', function(err) {
  console.error(err)
})

child.stdout.pipe(process.stdout)
child.stderr.pipe(process.stderr)
child.on('exit', function() {
  console.log('child.exit', id + 1)
})

process.on('exit', function() {
  console.error('exit', id);
})
console.log(process.execPath)

setTimeout(function(xs) {
  console.log('killing', id + 1)
  child.kill()
}, id === 0 ? 5000 : 10000)

which terminates in:

killing 1
child.exit 1
exit 0

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants