Reputation: 3073
I have an async function that creates a read stream and writes it to an http response, like so:
let handle = await getFile();
let stream = handle.createReadStream();
let stat = await handle.stat();
res.setHeader("content-length", stat.size);
res.setHeader("content-type", "application/octet");
res.statusCode = 200;
stream.pipe(res);
stream.on('close', () => {
handle.close();
res.end();
});
As you can see, I close the handle when my stream is closed, and also end the response for good measure. Yet, I see node logging this occasionally:
(node:54119) Warning: Closing file descriptor 21 on garbage collection
(Use `node --trace-warnings ...` to show where the warning was created)
(node:54119) [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.
There are no errors in my HTTP responses and I have verified with a log that my handle.close()
is getting called for every request. Why does node think that I have unclosed file descriptors?
Upvotes: 0
Views: 359
Reputation: 1
I had a similar issue, and on checking the types, I found that handle.close()
returns a Promise. So even awaiting on handle.close()
is also a valid approach.
let handle = await getFile();
let stream = handle.createReadStream();
let stat = await handle.stat();
res.setHeader("content-length", stat.size);
res.setHeader("content-type", "application/octet");
res.statusCode = 200;
stream.pipe(res);
stream.on('close', async () => {
await handle.close();
res.end();
});
Upvotes: 0
Reputation: 3073
It was because my async function was returning before the stream was done writing. I fixed it by wrapping it with a promise and awaiting it:
let handle = await getFile();
let stream = handle.createReadStream();
let stat = await handle.stat();
res.setHeader("content-length", stat.size);
res.setHeader("content-type", "application/octet");
res.statusCode = 200;
await new Promise<void>((resolve, reject) => {
stream.pipe(res);
stream.on('close', () => {
handle.close();
res.end();
resolve();
});
});
Upvotes: 0