【发布时间】: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 } 传递给我正在使用的任何读/写流,但无济于事。
- 为什么会这样?
- 我该如何阻止它?
谢谢
【问题讨论】:
-
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