Skip to content

Conversation

@Himanshu25Sahu
Copy link

@Himanshu25Sahu Himanshu25Sahu commented Oct 22, 2025

Clarify Race Condition in Blocking vs Non-Blocking Docs

This PR updates the “Dangers of Mixing Blocking and Non-Blocking Code” section with a revised example to reliably demonstrate the danger of mixing blocking and non-blocking calls.

Tested on Windows 10 Home 22H2 with Node.js v22.20.0 and v25.0.0, where the original example showed inconsistent behavior due to Windows file handle persistence.


🧩 Original Issue Description

In the Overview of Blocking vs Non-Blocking article, the section “Dangers of Mixing Blocking and Non-Blocking Code” included this example:

const fs = require('node:fs');

fs.readFile('/file.md', (err, data) => {
  if (err) {
    throw err;
  }
  console.log(data);
});
fs.unlinkSync('/file.md');

The text stated: “In the above example, fs.unlinkSync() is likely to be run before fs.readFile(), which would delete file.md before it is actually read.” However, testing revealed that fs.readFile() often succeeded on Windows due to file handle behavior, contradicting the implied failure.

Changes Made

  • Replaced the original example with a new one using a temporary file (temp.md) and fs.unlinkSync before fs.readFile to ensure a consistent ENOENT failure, demonstrating the danger reliably.
    Retained the original description’s intent, clarifying the race condition without altering its core message.
    Added a try-finally block for cleanup and a note about asynchronous output.

✅ Updated Documentation Text
The revised example:

const fs = require('node:fs');
const path = require('node:path');

const tempFile = path.join(__dirname, 'temp.md');
try {
  fs.writeFileSync(tempFile, 'Temporary content');
  fs.unlinkSync(tempFile);
  fs.readFile(tempFile, (err, data) => {
    if (err) {
      console.log('Error: Read failed with', err.code, 'as expected due to prior deletion.');
    } else {
      console.log('Unexpected success:', data.toString());
    }
  });
} finally {
  if (fs.existsSync(tempFile)) {
    fs.unlinkSync(tempFile);
  }
}

Description: “In the above example, fs.unlinkSync() is run before the asynchronous fs.readFile() operation, which deletes temp.md before the read can occur. This results in a failure (e.g., ENOENT error), demonstrating the danger of mixing blocking and non-blocking calls without proper sequencing. The try-finally block ensures file management.”

Note: Due to the asynchronous nature of fs.readFile, the console.log may not execute immediately. You might need to add a setTimeout or keep the process alive (e.g., with process.stdin.resume()) to see the output.

The safe alternative remains:

const fs = require('node:fs');
const path = require('node:path');

const tempFile = path.join(__dirname, 'temp.md');
fs.writeFileSync(tempFile, 'Temporary content');

fs.readFile(tempFile, (readFileErr, data) => {
  if (readFileErr) {
    throw readFileErr;
  }
  console.log(data);
  fs.unlink(tempFile, unlinkErr => {
    if (unlinkErr) {
      throw unlinkErr;
    }
  });
});

References

Original issue context from https://nodejs.org/en/learn/asynchronous-work/overview-of-blocking-vs-non-blocking
Repository: https://github.com/nodejs/nodejs.org
fixes #8253

@Himanshu25Sahu Himanshu25Sahu requested a review from a team as a code owner October 22, 2025 07:03
@vercel
Copy link

vercel bot commented Oct 22, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
nodejs-org Ready Ready Preview Oct 22, 2025 0:17am

@Himanshu25Sahu Himanshu25Sahu changed the title Clarify race condition in blocking vs non-blocking docs Clarify race condition in blocking vs non-blocking docs (#8253) Oct 22, 2025
@Himanshu25Sahu Himanshu25Sahu changed the title Clarify race condition in blocking vs non-blocking docs (#8253) Clarify race condition in blocking vs non-blocking docs (Issue: #8253) Oct 22, 2025
@Himanshu25Sahu Himanshu25Sahu changed the title Clarify race condition in blocking vs non-blocking docs (Issue: #8253) Clarify race condition in blocking vs non-blocking docs (Fixes: #8253) Oct 22, 2025
@Himanshu25Sahu Himanshu25Sahu changed the title Clarify race condition in blocking vs non-blocking docs (Fixes: #8253) Clarify race condition in blocking vs non-blocking docs (fixes #8253) Oct 22, 2025
Copy link
Member

@avivkeller avivkeller left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example's description was accurate prior to this change.

The issue referenced described an issue with the example code, so, if anything, the example itself should be changed, not its description.

@Himanshu25Sahu
Copy link
Author

Hi @avivkeller I've updated the PR with the revised example. Please let me know if any modifications are required.


There are some patterns that should be avoided when dealing with I/O. Let's look
at an example:
There are some patterns that should be avoided when dealing with I/O. Let's look at an example:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated change

at an example:
There are some patterns that should be avoided when dealing with I/O. Let's look at an example:

```js
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example change isn't what we want.

We want:

operationWithCallback(() => { ... })
operationWithoutCallback()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A code example doesn't seem to work as described

2 participants