dougwilson/nodejs-depd

Calling `process.cwd()` from index.js can be problematic

ohz10 opened this issue · 4 comments

ohz10 commented

The following line in index.js can crash some node apps.

var basePath = process.cwd()

This line in index.js is problematic for some node applications that might get invoked from a directory that has been removed by another process.

The application may not actually need the current working directory, but it never gets a chance to run because node barfs if depd is a dependency of anything pulled in with a requires statement.

I haven't looked into why you need this, but maybe __filename or __dirname would be more appropriate here? Since it would be hard to execute a node app that didn't exist.

Hm, that is an interesting scenario. Unfortunately __filename and __dirname don't work for the use case, as those of course represent very different locations and are not interchangeable.

Regardless we can work around this issue. I assume that by crash you mean that it throws an error? Do you happen to have the specific error it throws on hand you can paste here?

ohz10 commented

Steps to reproduce:

Create a project directory issue_45 and a package.json in it.

// package.json
{
  "name": "test",
  "version": "0.0.1",
  "description": "demonstrate depd issue 45",
  "license": "Public Domain",
  "dependencies": {
    "depd": "~1.1.2"
  }
}

Install dependencies, $ npm install -save

// issue_45.js
var depd = require('depd');
console.log('issue 45');

Make another directory, and cd into it. It doesn't particularly matter where.

$ mkdir test && cd test

Not from another terminal, remove the directory you created.

$ rmdir test

Now from the original terminal use the absolute path to invoke issue_45.js.

$ node /Users/<user>/issue_45/issue_45.js

$ node /Users/<user>/issue_45/issue_45.js
internal/bootstrap/switches/does_own_process_state.js:130
    cachedCwd = rawMethods.cwd();
                           ^

Error: ENOENT: no such file or directory, uv_cwd
    at process.wrappedCwd [as cwd] (internal/bootstrap/switches/does_own_process_state.js:130:28)
    at Object.<anonymous> (/Users/<user>/issue_45/node_modules/depd/index.js:25:24)
    at Module._compile (internal/modules/cjs/loader.js:1072:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)
    at Module.load (internal/modules/cjs/loader.js:937:32)
    at Function.Module._load (internal/modules/cjs/loader.js:778:12)
    at Module.require (internal/modules/cjs/loader.js:961:19)
    at require (internal/modules/cjs/helpers.js:92:18)
    at Object.<anonymous> (/Users/<user>/issue_45/issue_45.js:1:12)
    at Module._compile (internal/modules/cjs/loader.js:1072:14) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'uv_cwd'
}

If you happen to be executing TypeScript bundled with webpack, the error message is not as friendly, it doesn't mention depd in the call stack, but you get the same error message.

You might be wondering how this could possibly happen. We've bundled a web service and some CLI tools for managing it into a single pack, and the CLI is installed in /opt/local/bin/. Some directories that hold state for the web service get deleted when some components are reconfigured & a customer was poking around the filesystem during a restart & happened to invoked the CLI tool from a deleted directory.

ohz10 commented

@dougwilson would there be any negative consequences to wrapping process.cwd() in a try/catch block and setting it to undefined or null on error?

Something like this:

function tryCwd() {
  try {
    return process.cwd();
  } catch(e) {
    return undefined;
  }
}

var basePath = tryCwd()