Node.js -如何防止被中断的子进程存活
Node.js - How can I prevent interrupted child processes from surviving?
我发现如果调用脚本被中断,一些子进程无法终止。
具体来说,我有一个使用Ghostscript执行各种操作的模块:提取页面图像,从切片创建新的pdf等。我使用以下命令来执行该命令,并返回子标准输出的through流:
function spawnStream(command, args, storeStdout, cbSuccess) {
storeStdout = storeStdout || false;
const child = spawn(command, args);
const stream = through(data => stream.emit('data', data));
let stdout = '';
child.stdout.on('data', data => {
if (storeStdout === true) stdout += data;
stream.write(data);
});
let stderr = '';
child.stderr.on('data', data => stderr += data);
child.on('close', code => {
stream.emit('end');
if (code > 0) return stream.emit('error', stderr);
if (!!cbSuccess) cbSuccess(stdout);
});
return stream;
}
可由以下函数调用:
function extractPage(pathname, page) {
const internalRes = 96;
const downScaleFactor = 1;
return spawnStream(PATH_TO_GS, [
'-q',
'-sstdout=%stderr',
'-dBATCH',
'-dNOPAUSE',
'-sDEVICE=pngalpha',
`-r${internalRes}`,
`-dDownScaleFactor=${downScaleFactor}`,
`-dFirstPage=${page}`,
`-dLastPage=${page}`,
'-sOutputFile=%stdout',
pathname
]);
}
被使用,例如:
it('given a pdf pathname and page number, returns the image as a stream', () => {
const document = path.resolve(__dirname, 'samples', 'document.pdf');
const test = new Promise((resolve, reject) => {
const imageBlob = extract(document, 1);
imageBlob.on('data', data => {
// do nothing in this test
});
imageBlob.on('end', () => resolve(true));
imageBlob.on('error', err => reject(err));
});
return Promise.all([expect(test).to.eventually.equal(true)]);
});
当这被中断时,例如,如果测试超时或发生未处理的错误,子进程似乎没有接收到任何信号并存活下来。这有点令人困惑,因为没有一个单独的操作特别复杂,但进程似乎可以无限期地生存,使用100%的CPU。
☁ ~ ps aux | grep gs | head -n 5
rwick 5735 100.0 4.2 3162908 699484 s000 R 12:54AM 6:28.13 gs -q -sstdout=%stderr -dBATCH -dNOPAUSE -sDEVICE=pngalpha -r96 -dDownScaleFactor=1 -dFirstPage=3 -dLastPage=3 -sOutputFile=%stdout /Users/rwick/projects/xan-desk/test/samples/document.pdf
rwick 5734 100.0 4.2 3171100 706260 s000 R 12:54AM 6:28.24 gs -q -sstdout=%stderr -dBATCH -dNOPAUSE -sDEVICE=pngalpha -r96 -dDownScaleFactor=1 -dFirstPage=2 -dLastPage=2 -sOutputFile=%stdout /Users/rwick/projects/xan-desk/test/samples/document.pdf
rwick 5733 100.0 4.1 3154808 689000 s000 R 12:54AM 6:28.36 gs -q -sstdout=%stderr -dBATCH -dNOPAUSE -sDEVICE=pngalpha -r96 -dDownScaleFactor=1 -dFirstPage=1 -dLastPage=1 -sOutputFile=%stdout /Users/rwick/projects/xan-desk/test/samples/document.pdf
rwick 5732 100.0 4.2 3157360 696556 s000 R 12:54AM 6:28.29 gs -q -sstdout=%stderr -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=%stdout /Users/rwick/projects/xan-desk/test/samples/document.pdf /Users/rwick/projects/xan-desk/test/samples/page.pdf
我想使用计时器发送一个杀死信号给子进程,但选择一个任意的间隔来杀死一个进程似乎会有效地将一个已知的问题换成一个未知的问题,并把它踢到路上。
如果你能告诉我我遗漏了什么,我将非常感激。是否有更好的选择来封装子进程,以便父进程的终止更有可能引发子进程的中断?
监听错误事件
child.on('error', function(err) {
console.error(err);
// code
try {
// child.kill() or child.disconnect()
} catch (e) {
console.error(e);
}
});
相关文章:
- 子进程未接收消息
- 如何通过子进程连接Java应用程序后在node.js中编写文件
- 节点.js子进程中的运行函数
- 如何将画布对象从子进程流式传输回 Node.js
- 如何在Firefox插件中向子进程发送消息,如Chrome原生消息
- 从生成的子进程中获取信息的最佳方法
- 在 Node.js 中使用 Jasmine 测试子进程发送
- 在快速服务器中生成子进程
- 如何在 node.js 中关闭子进程的 stdio 管道
- 如何使用并行子进程在大型数组上执行“工作”
- 使用 node.js (子进程) 运行 shell 脚本
- 如何从nodejs中的守护进程生成gpg子进程
- Cloud9 在生成子进程时抛出错误,是否有解决方法
- 如何在从 Meteor.method 返回之前等待子进程结果
- 将输入数据发送到节点.js中的子进程
- 完成时的子进程事件
- 如何在 Debian 上通过 node.js 中的引用变量停止子进程
- Node.js为什么不立即启动子进程
- 通过Node.js子进程关闭CS:GO专用服务器
- Node.js -如何防止被中断的子进程存活