You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TLDR: It seems that file watchers are preventing the exit handler from properly firing on a child process that I have started, specifically when the exit handler is registered inside a SIGINT handler.
Minimal repro code, with problematic line commented out
Try running this program and pressing Ctrl+C -- the child exits as expected.
If the commented line is uncommented (await watcher.stop()), the child process exits (I see bash: Got SIGINT, exiting. printed), but the exit listener does not get fired, so the program hangs forever.
Interestingly, if the 'exit' listener is registered before stopping file watchers, everything works fine:
Repro modified to register exit listener before stopping file watchers
constchild_process=require('child_process');constfs=require('fs');constnsfw=require('nsfw');constproc=child_process.spawn('bash',['-c',` trap "echo bash: Got SIGINT, exiting. ; exit 1" SIGINT sleep infinity `],{stdio: 'inherit'});letwatcher;constonExit=newPromise((resolve)=>{proc.on('exit',()=>{console.log('Child process exited.');resolve();});});process.on('SIGINT',async()=>{console.log('Got SIGINT.');if(watcher){console.log('Stopping file watcher.');awaitwatcher.stop();watcher=null;}console.log('Forwarding SIGINT to child.');proc.kill('SIGINT');awaitonExit;process.exit(1);});(async()=>{constwatchPath='/tmp/watch_path';fs.mkdirSync(watchPath,{recursive: true});(watcher=awaitnsfw(watchPath,()=>{})).start();console.log('Press Ctrl+C to stop child process');})();
So it appears that starting file watchers is preventing subsequently registered exit listeners from firing. But maybe it's because I am trying to register the 'exit' listener inside a SIGINT handler? Indeed, it appears to have something to do with the SIGINT handler, because if I stop file watchers and register the exit listener in the main function, it works fine:
Repro modified to stop file watchers and register exit listener in main function
constchild_process=require('child_process');constfs=require('fs');constnsfw=require('nsfw');constproc=child_process.spawn('bash',['-c',` trap "echo bash: Got SIGINT, exiting. ; exit 1" SIGINT sleep infinity `],{stdio: 'inherit'});letwatcher;letonExit;process.on('SIGINT',async()=>{console.log('Got SIGINT.');console.log('Forwarding SIGINT to child.');proc.kill('SIGINT');awaitonExit;process.exit(1);});(async()=>{constwatchPath='/tmp/watch_path';fs.mkdirSync(watchPath,{recursive: true});(watcher=awaitnsfw(watchPath,()=>{})).start();awaitwatcher.stop();onExit=newPromise((resolve)=>{proc.on('exit',()=>{console.log('Child process exited.');resolve();});});console.log('Press Ctrl+C to stop child process');})();
I am also pretty sure that this is not a general issue with calling await inside a SIGINT handler, and has something specifically to do with file watchers. If I replace the await watcher.stop() with await new Promise(resolve => setTimeout(resolve, 500)), it works:
Minimal example without use of nsfw, demonstrating that the problem is likely nsfw-specific
constchild_process=require('child_process');constproc=child_process.spawn('bash',['-c',` trap "echo bash: Got SIGINT, exiting. ; exit 1" SIGINT sleep infinity `],{stdio: 'inherit'});process.on('SIGINT',async()=>{console.log('Got SIGINT.');console.log('Waiting a bit...')awaitnewPromise(resolve=>setTimeout(resolve,500));console.log('Forwarding SIGINT to child.');proc.kill('SIGINT');awaitnewPromise((resolve)=>{proc.on('exit',()=>{console.log('Child process exited.');resolve();});});process.exit(1);});(async()=>{console.log('Press Ctrl+C to stop child process');})();
Linux kernel version: 5.13.0-28-generic Distro: Ubuntu 20.04
The text was updated successfully, but these errors were encountered:
TLDR: It seems that file watchers are preventing the
exit
handler from properly firing on a child process that I have started, specifically when the exit handler is registered inside a SIGINT handler.Minimal repro code, with problematic line commented out
Try running this program and pressing Ctrl+C -- the child exits as expected.
If the commented line is uncommented (
await watcher.stop()
), the child process exits (I seebash: Got SIGINT, exiting.
printed), but theexit
listener does not get fired, so the program hangs forever.Interestingly, if the
'exit'
listener is registered before stopping file watchers, everything works fine:Repro modified to register exit listener before stopping file watchers
So it appears that starting file watchers is preventing subsequently registered
exit
listeners from firing. But maybe it's because I am trying to register the'exit'
listener inside aSIGINT
handler? Indeed, it appears to have something to do with the SIGINT handler, because if I stop file watchers and register the exit listener in the main function, it works fine:Repro modified to stop file watchers and register exit listener in main function
I am also pretty sure that this is not a general issue with calling
await
inside a SIGINT handler, and has something specifically to do with file watchers. If I replace theawait watcher.stop()
withawait new Promise(resolve => setTimeout(resolve, 500))
, it works:Minimal example without use of nsfw, demonstrating that the problem is likely nsfw-specific
Linux kernel version: 5.13.0-28-generic
Distro: Ubuntu 20.04
The text was updated successfully, but these errors were encountered: