Course contentsShow
← Node.js
Lesson 326 of 1,9804. I/O and File System OperationsFree lesson

The Event Loop and File Descriptor Lifecycle

Trace the lifecycle of a file descriptor from kernel allocation to resource cleanup within the Node.js event loop.

In this lesson, you will learn how a file descriptor travels from the operating system kernel into the Node.js event loop and how it is eventually released.

The Kernel Handshake

When you request a file operation, such as fs.open(), Node.js asks your operating system (the kernel) for access to that resource. The kernel allocates a File Descriptor (FD)—a small, non-negative integer that acts as a unique handle for that open file. This integer is the kernel's way of tracking your process’s interaction with the hardware or file system.

Entry into the Event Loop

Once the FD is granted, Node.js wraps it in an internal C++ object managed by libuv. The Event Loop does not "hold" the file; instead, it registers the FD with a multiplexing mechanism (like epoll on Linux).

Think of the Event Loop as a manager sitting at a desk. When you perform an async read, the manager hands the FD to the kernel and says, "Let me know when this is ready." The Event Loop continues to process other tasks, keeping your application responsive while the kernel waits for the disk or network to complete the I/O.

The Lifecycle of Resource Cleanup

The lifecycle ends when the operation completes. Once the data is retrieved, a callback is queued in the Event Loop’s poll phase. Crucially, if you don't explicitly close the file descriptor (using fs.close() or by using high-level abstractions like fs.promises), the FD stays open in your process's table.

const fs = require('fs/promises');

async function processFile(path) {
  const handle = await fs.open(path, 'r'); // FD allocated here
  try {
    const data = await handle.readFile();
    console.log(data.toString());
  } finally {
    await handle.close(); // FD released back to the OS
  }
}

If you fail to call .close(), you trigger a resource leak. Even if the JavaScript object is garbage collected, the kernel's file descriptor remains assigned to your process. If you accumulate enough of these "zombie" descriptors, your application will eventually crash with an "EMFILE: too many open files" error, effectively stalling the Event Loop from initiating any new I/O.

Key Takeaway: The Event Loop acts as the coordinator for I/O, but the developer is responsible for ensuring that File Descriptors are explicitly closed so the kernel can reclaim those resources.