Skip to content

EBADF thrown by stream if file is explicitly closed in v15 #35862

Closed
@alekitto

Description

@alekitto

An unexpected EBADF error is thrown if a stream is open on a file and then the file is explicitly closed.
The explicit close call is required if using fs/promises, otherwise a warning is emitted.

  • Version: v15.0.1
  • Platform: Darwin Kernel Version 19.6.0: Mon Aug 31 22:12:52 PDT 2020; root:xnu-6153.141.2~1/RELEASE_X86_64 x86_64 (macOS Catalina 10.15.7)
  • Subsystem: fs

What steps will reproduce the bug?

I've created a simple case that generates the error.
TESTFILE.txt exists and could be empty.

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

(async () => {
    const handle = await fsPromises.open('TESTFILE.txt', 'r');
    const stream = fs.createReadStream(null, {
        fd: handle.fd,
        autoClose: false,
    });

    await handle.close();
})();

How often does it reproduce? Is there a required condition?

Always

What is the expected behavior?

No error.

What do you see instead?

The following error is thrown:

node:events:304
      throw er; // Unhandled 'error' event
      ^

Error: EBADF: bad file descriptor, read
Emitted 'error' event on ReadStream instance at:
    at emitErrorNT (node:internal/streams/destroy:194:8)
    at errorOrDestroy (node:internal/streams/destroy:257:7)
    at node:internal/fs/streams:193:9
    at FSReqCallback.wrapper [as oncomplete] (node:fs:539:5) {
  errno: -9,
  code: 'EBADF',
  syscall: 'read'
}

If autoClose is omitted or true, the thrown error is:

node:events:304
      throw er; // Unhandled 'error' event
      ^

Error: EBADF: bad file descriptor, close
Emitted 'error' event on ReadStream instance at:
    at emitErrorNT (node:internal/streams/destroy:194:8)
    at emitErrorCloseNT (node:internal/streams/destroy:159:3)
    at processTicksAndRejections (node:internal/process/task_queues:80:21) {
  errno: -9,
  code: 'EBADF',
  syscall: 'close'
}

This last error is thrown also if stream.destroy() is called before handle.close().

The only way to avoid the error is to not call handle.close, but this generates a deprecation warning in a more complex application (Closing a FileHandle object on garbage collection is deprecated.)

Additional information

No error is emitted on previous node versions (10-14).

Metadata

Metadata

Assignees

No one assigned

    Labels

    streamIssues and PRs related to the stream subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions