【发布时间】:2016-04-05 14:33:37
【问题描述】:
我无法在信号处理程序中使用process.exit() 让我的nodejs 应用程序退出。这是因为我在 Linux 输入事件节点 (/dev/input/mouse1) 上有一个挂起的读取操作。我花了几个小时研究,但我只能找到this SO question。我尝试使用fs.ReadStream 就像在那里使用的那样并调用它的destroy 方法,但它也没有工作。即使通过阅读 nodejs 源代码,我也无法想出一个主意。然后是这个issue on github,有点相关。
到目前为止,我想出了一些技巧来解决这个问题,但没有什么干净的:
- 使用比
process.exit更强的东西,也许process.abort - 生成一个子进程 (
childProcess.fork) 到read,我可以从父进程终止它。但这会创建一个新的 nodejs 实例,内存使用量约为 10mb。 - 用我可以更好地控制正在发生的事情(使用线程等)的语言 (C++) 编写程序并从 javascript 调用它。虽然我更喜欢留在 js-land。
- 或者也许有人知道可以帮助我以不同方式实现目标的工具? (请参阅下面的背景信息)。也许我不必使用
/dev/input/
基本上,我需要一种直接或间接取消挂起的read 操作的方法(例如,通过从active_handles 列表中清除它们)。
提前感谢您的回答!
示例
在下面的代码示例中,我可以按ctrl+c,但nodejs只有在我移动鼠标后才会退出:
'use strict'
const fs = require('fs');
const buf = new Buffer(24);
const mouse = fs.openSync('/dev/input/mouse1', 'r');
const onRead = (err, bytesRead, buffer) => {
console.log('read');
if (!err) {
process.nextTick(fs.read, mouse, buf, 0, buf.length, null, onRead);
}
};
fs.read(mouse, buf, 0, buf.length, null, onRead);
process.on('SIGINT', () => {
fs.closeSync(mouse);
process.exit();
});
背景资料
我正在开发一个基于运行 nodejs 脚本的树莓派的小项目。我希望程序通过 USB 鼠标的滚轮和 GPIO 附加按钮来响应用户输入。因此,我将onoff 库用于GPIO 的东西。 onoff 文档建议安装自定义 SIGINT 处理程序以在程序退出之前释放资源,这就是这种愿望的来源。为了在没有窗口系统甚至终端的情况下处理滚轮数据,我最终想让this library工作,但现在我遇到了上述问题。
【问题讨论】:
-
您是否检查过信号处理程序是否被实际调用?您使用
fs.openSync和fs.read而不是fs.createReadStream并添加read事件处理程序的任何具体原因?ps或top中的进程在尝试中断时处于什么状态? -
@jcaron 感谢您的回复。这段代码只是一个简单的例子。我在问题中提到我已经使用 ReadStream 测试了替代实现。此外,fs.ReadStream 只是 fs.read 的某种包装,请参阅here。处理程序被调用,您甚至可以从中
console.log。能否详细说明如何在top/ps中查找进程状态? -
我今天也偶然发现了这个。一种解决方案是使用诸如 node-hid 之类的库,它使用 hidapi,并在内部进行了足够的清理,但我想避免添加另一个需要编译的库。感谢您提供解决方法列表。最后,您是否设法为此找到了另一种解决方案?
-
@AndreT 这是 5 年前的事了:D 但 IIRC 这是一门我最终完全放弃的单门课程。所以恐怕没有解决办法。我遵循的最后一种方法是将我自己的事件输入设备,以便 nodejs 的 io lib 中的阻塞线程将恢复并允许我正确关闭。不确定我是否可以正常工作...