Home > database >  Nodejs "closing directory handle on garbage collection"
Nodejs "closing directory handle on garbage collection"

Time:07-31

Нello, the following is an excerpt from my code:

let dirUtility = async (...args) => {
  
  let dir = await require('fs').promises.opendir('/path/to/some/dir...');
  let entries = dir.entries();
  
  for await (let childDir of dir) doStuffWithChildDir(childDir);
  
  return entries;
  
};

This function is called a fair bit in my code. I have the following in my logs:

(node:7920) Warning: Closing directory handle on garbage collection
(Use `node --trace-warnings ...` to show where the warning was created)
(node:7920) Warning: Closing directory handle on garbage collection
(node:7920) Warning: Closing directory handle on garbage collection
(node:7920) Warning: Closing directory handle on garbage collection
(node:7920) Warning: Closing directory handle on garbage collection
  1. What exactly is the significance of these errors?
  2. Do they indicate a large issue? (Should I simply seek to silence these errors?)
  3. What is the best way to avoid this issue?

Thanks!

CodePudding user response:

Raina77ow’s answer tells you why the warning is displayed.

Basically what's happening is that the NodeJS runtime is implicity calling the close() method on the dir object, but the best practice is that you would explicity call the close() method on the handle, or even better wrap it in a try..finally block.

Like this:

let dirUtility = async (...args) => {
    let dir = await require('fs').promises.opendir('/path/to/some/dir...');

    try {
        let entries = dir.entries();
  
        for await (let childDir of dir) doStuffWithChildDir(childDir);
  
        return entries;
    }
    finally {
        dir.close();
        // return some dummy value, or return undefined.
    }
};

CodePudding user response:

Quoting the comments (source):

// If the close was successful, we still want to emit a process
// warning to notify that the file descriptor was gc'd. We want to be
// noisy about this because not explicitly closing the DirHandle is a
// bug.

While your code seems to be really similar to the code in this question, there's a difference:

let entries = dir.entries(); 
...
return entries;

That, in a nutshell, seems to create an additional iterator over directory, which is passed outside as the function's return value. How exactly this iterator is employed is not clear (as you don't show what happens next with dirUtility), but either it's not exhausted before GC takes its toll, or it's done in a way that confuses NodeJS.

Overall, the whole approach doesn't seem right to me: the function seems both to do something with a directory AND, essentially, give that directory back as its result, without actually caring how this object will be used. That, at least, looks like a leaky abstraction.

So it seems you need to decide: if you actually don't use the return value of dirUtility, just drop the corresponding lines of code. But if you actually do need to preserve the open directory (for example, for performance reasons), consider creating a stateful wrapper around it, encapsulating the value. That should prevent GC this handle, as long as the corresponding object lives in your code.

  • Related