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

Node.js-使用多个流正确关闭fd,node.js,filesystems,file-descriptor,Node.js,Filesystems,File Descriptor,我正在创建一个append/rw文件(取决于是否继续下载) 稍后,我为该FD创建一个写流 let writeStream = fs.createWriteStream(null, {fd:this.syncFile.fd, autoClose:false, highWaterMark: 1024*1024}); 下载剩余数据后,我可能会也可能不会为同一FD创建readStream,以计算完整文件的校验和 let readStream = fs.createReadStream(null, {f

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

稍后,我为该FD创建一个写流

let writeStream = fs.createWriteStream(null, {fd:this.syncFile.fd, autoClose:false, highWaterMark: 1024*1024});
下载剩余数据后,我可能会也可能不会为同一FD创建readStream,以计算完整文件的校验和

let readStream = fs.createReadStream(null, {fd:this.syncFile.fd, autoClose:false, highWaterMark: 1024*1024, start:0});
为了最终确定,我想关闭FD

fs.closeSync(this.syncFile.fd);
我在readStream/writeStream上尝试了许多与close()或dispose()的组合 我总是得到一些意想不到的例外

[Window Title]
Error
[Content]
Uncaught Exception:
Error: EBADF: Closing file descriptor 5 on garbage collection failed, close
或控制台关于关闭gc上的文件描述符的警告 总是连续两个,有时后面跟着

错误:EBADF:错误的文件描述符,写入

为什么会这样?读/写流具有选项
autoClose:true
而且,以前,当我只有一个writeStream时,一些我无法重新创建的组合起了作用

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

如果我愿意的话

删除此.sync文件
我收到了一封漂亮的垃圾邮件

(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

但没有例外,无论是否已处理,但由于上面列出的问题,这仍然不够好。我唯一的选择似乎是强制GC收集?

如果您使用
fs.promises.open()
打开文件,那么您将获得较新的
FileHandle
对象(不是常规的文件描述符),并且您需要在该对象上调用close,如
FileHandle.close()
,而不是
fs.close(fd)
确定,您没有使用自动关闭,因此必须手动关闭。您需要钩住正确的事件,以便能够自己关闭它。对于readStream,这通常是
end
事件,表示连续读取内容的结束。对于writeStream,这取决于您如何使用它,因为只有您知道您何时在对它进行写入。我们需要看到您的整个真实代码流,以便知道如何在这里帮助您。这是特定于流的使用和特定代码的。这里没有通用的答案。此外,如果您使用
fs.promises.open()
打开文件,那么您将获得较新的FileHandle对象(不是常规的文件描述符),并且您需要像中一样对该对象调用close,而不是
fs.close(fd)
@jfriend00,如果我不关闭
自动关闭:false
流,无论如何,它们都会在垃圾收集期间尝试关闭FD,并会出现一个漂亮的错误消息框,因为它在主循环中是一个未捕获的异常。如果我对其中任何一个调用
destroy()
close()
,所有其他关闭FD的尝试都会导致异常。如果我
删除readStream
它们和主
文件句柄
将起作用,但该文件在下次GC运行之前不会释放,会阻止所有其他程序使用它。@jfriend00第二条注释正确,
this.syncFile.close()
而不是
fs.closeSync(this.syncFile.fd)
删除writeStream/readStream后使用的
似乎工作正常,请作为答案发布,谢谢!:)(但是,在流上调用
close()
destroy()
或在调用之前不删除它们仍然会导致随机错误。)
(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