Node.js - 正确关闭多个流的 fd

n00*_*00b 4 filesystems file-descriptor node.js

我正在创建一个append/rw文件(取决于下载是否恢复)

this.syncFile = await fs.promises.open(this.syncPath, 'a+');
this.syncFile = await fs.promises.open(this.syncPath, 'r+');
Run Code Online (Sandbox Code Playgroud)

后来我为该 FD 创建一个写入流

let writeStream = fs.createWriteStream(null, {fd:this.syncFile.fd, autoClose:false, highWaterMark: 1024*1024});
Run Code Online (Sandbox Code Playgroud)

下载剩余数据后,我可能会也可能不会为同一个 FD 创建 readStream 来计算完整文件的校验和

let readStream = fs.createReadStream(null, {fd:this.syncFile.fd, autoClose:false, highWaterMark: 1024*1024, start:0});
Run Code Online (Sandbox Code Playgroud)

为了最终确定,我想关闭FD。

fs.closeSync(this.syncFile.fd);
Run Code Online (Sandbox Code Playgroud)

我在 readStream/writeStream 上尝试了与 close() 或 dispose() 的多种组合,但我不断收到未捕获的异常

[Window Title]
Error
[Content]
Uncaught Exception:
Error: EBADF: Closing file descriptor 5 on garbage collection failed, close
Run Code Online (Sandbox Code Playgroud)

或关于关闭 gc 上的文件描述符的控制台警告总是连续两个,有时后面跟着

Error: EBADF: bad file descriptor, write

为什么会发生这种情况?读/写流有选项autoClose:true 此外,之前,当我只有一个 writeStream 时,我无法重新创建一些组合。

在这种情况下关闭所有流和FD的正确方法是什么?我不能等待 GC 关闭文件描述符,因为它在文件上持有独占锁,我正在更改其属性的文件 ( child_process.execSync('attrib -h +r "' + this.finalPath + '"');) 另外,在触发 GC 之前,其他程序无法使用该文件。

如果我只做

delete this.syncFile; 我收到一封漂亮的垃圾邮件

(node:25180) Warning: Closing file descriptor 10 on garbage collection
(node:25180) Warning: Closing file descriptor 10 on garbage collection
(node:25180) Warning: Closing file descriptor 8 on garbage collection
(node:25180) Warning: Closing file descriptor 8 on garbage collection
(node:25180) Warning: Closing file descriptor 7 on garbage collection
(node:25180) Warning: Closing file descriptor 7 on garbage collection
(node:25180) Warning: Closing file descriptor 9 on garbage collection
(node:25180) Warning: Closing file descriptor 9 on garbage collection
Run Code Online (Sandbox Code Playgroud)

但没有例外,无论是处理还是其他方式,但这仍然不够好,因为上面列出的问题。我唯一的选择似乎是强制GC收集?

jfr*_*d00 9

如果您使用 打开文件fs.promises.open(),那么您将获得较新的FileHandle对象(不是常规文件描述符),并且您将需要像 中那样调用该对象的 close fileHandle.close(),而不是fs.close(fd)