【问题标题】:Stop nodejs from garbage collection / automatic closing of File Descriptors停止 nodejs 从垃圾收集/自动关闭文件描述符
【发布时间】:2022-01-07 01:28:42
【问题描述】:

考虑一个数据库引擎,它对外部打开的文件(如 SQLite)进行操作,但文件句柄被传递给它的构造函数。我正在为我的应用程序使用这样的设置,但似乎无法弄清楚为什么 NodeJS 坚持在 2 秒的操作后关闭文件描述符。我需要那东西保持打开状态!

const db = await DB.open(await fs.promises.open('/path/to/db/file', 'r+'));
...
(node:100840) Warning: Closing file descriptor 19 on garbage collection
(Use `node --trace-warnings ...` to show where the warning was created)
(node:100840) [DEP0137] DeprecationWarning: Closing a FileHandle object on garbage collection is deprecated. Please close FileHandle objects explicitly using FileHandle.prototype.close(). In the future, an error will be thrown if a file descriptor is closed during garbage collection.

DB 类在很长一段时间内广泛使用提供的文件描述符,因此关闭它相当烦人。在那个类中,我使用诸如readFile、createReadStream() 和readline 模块之类的方法来单步执行文件的行。我将 { autoClose: false, emitClose: false } 传递给我正在使用的任何读/写流,但无济于事。

  1. 为什么会这样?
  2. 我该如何阻止它?

谢谢

【问题讨论】:

  • DB 对象是什么?哪个数据库?这似乎是 db 变量超出范围并被垃圾收集,因此没有任何东西可以使用数据库,因此它有资格进行垃圾收集。
  • 哦,那是我自己写的。它实际上只是一个内置了一堆解析器的类,用于导航文本文件。这是gist
  • 我怀疑你在这个for await (const line of readline.createInterface({input: file.createReadStream({start: 0, autoClose: false})})) 中使用await 时遇到了一个邪恶的问题。如果您在其他任何地方使用await,则底层流会触发其所有data 事件并完成,在某些情况下,您的进程甚至会在您处理任何数据事件之前退出。 IMO,这是一个糟糕的设计。
  • 我自己也遇到过这个问题,并帮助了这里遇到同样问题的多个其他人。基本上,当您在流上使用此异步迭代器时,您不能使用任何其他await,否则您将错过流上的事件。我认为需要修复设计,以便流不会触发事件,除非为 asyncIterator 上的 await 服务。
  • 有趣的是,您应该提到这一点,因为在调用 commit() 方法后,我在这里检测到一些奇怪的格式问题。

标签: node.js garbage-collection filesystems


【解决方案1】:

我怀疑你在使用 await 时遇到了一个邪恶的问题

for await (const line of readline.createInterface({input: file.createReadStream({start: 0, autoClose: false})}))

如果您在for 循环块(您是)中的任何其他位置使用await,则底层流会触发其所有data 事件并完成(而您在另一个await 并且在某些情况下在这种情况下,您的进程甚至在您处理流中的任何 data 或 line 事件之前就退出了。这是一个真正有缺陷的设计,并且已经伤害了许多其他人。

解决此问题的最安全方法是根本不使用asyncIterator,而只需在 readline 对象的常规事件中自己包装一个 promise。

【讨论】:

  • 再次感谢您的所有帮助@jfriend00。我自己无法解决这个问题。
  • @J-Cake - 是的,我只知道这个,因为它在我自己的编程中咬了我一口。就我而言,除了简单的演示代码之外,readline asyncIterator 几乎都被破坏了。整个 readline 界面对我来说总是很混乱。为什么在世界上,你会在与 tty 提示相同的界面中逐行读取文件,我不知道。而且,很明显,asyncIterator 只是在没有真正考虑在流动的流之上执行此操作的问题的情况下才安装的。它们是不兼容的模型,没有更多代码来控制流。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-27
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
  • 2016-11-18
  • 1970-01-01
相关资源
最近更新 更多