isaacs / node-graceful-fs

fs with incremental backoff on EMFILE
ISC License
1.27k stars 147 forks source link

Cannot be used in Worker threads (Node 10.x) #204

Closed RomainMuller closed 3 years ago

RomainMuller commented 3 years ago

The module cannot be loaded within a Worker thread, as process.chdir is not available (undefined) in there. The following line causes a TypeError: Object prototype may only be an Object or null: undefined:

https://github.com/isaacs/node-graceful-fs/blob/feedd03814a6fd4dbf3387c092fddde61dbab2bc/polyfills.js#L22

I reckon the solution would be to have graceful-fs also not provide chdir in this scenario.

vijayshukla30 commented 3 years ago

When you going to release this fix getting error not able to even start the application.

Screenshot 2021-02-08 at 8 19 08 PM
coreyfarrell commented 3 years ago

What version of node.js does this effect? In my tests typeof process.chdir === 'function' from a worker thread.

RomainMuller commented 3 years ago

At least in node 10, as per https://nodejs.org/docs/latest-v10.x/api/process.html#process_process_chdir_directory:

This feature is not available in Worker threads.

Although the same note still stands on the latest release, although it appears to be defined there:

/// worker-demo.js

const { Worker, isMainThread, parentPort } = require('worker_threads');

if (isMainThread) {
  const worker = new Worker(__filename);
  worker.on('message', ({ chdir }) => console.error(`(${process.version}) process.chdir is a ${chdir}`))
} else {
  parentPort.postMessage({ chdir: typeof process.chdir });
}
$ /usr/local/opt/node@10/bin/node --experimental-worker worker-demo.js
(v10.23.2) process.chdir is a undefined

$ /usr/local/opt/node@12/bin/node --experimental-worker worker-demo.js
(v12.20.1) process.chdir is a function
mf-corey commented 3 years ago

Thanks for the quick fix on this issue. I encountered it as well, it was preventing my Electron app from starting in node 10.20.1. The fix merged in this PR is the correct strategy, but I had luck launching my app with this small stop-gap that swallows the error... Use at your own risk.

var originalSetPrototypeOf = Object.setPrototypeOf;
Object.setPrototypeOf = function(a, b) {
  try {
    return originalSetPrototypeOf.apply(null, arguments);
  } catch (_error) {
    return console.error(_error);
  }
};