nodejs / node

Node.js JavaScript runtime ✨🐢🚀✨
https://nodejs.org
Other
107.4k stars 29.51k forks source link

listen: Misleading error message when directory of IPC socket does not exist #35538

Open alois31 opened 4 years ago

alois31 commented 4 years ago

What steps will reproduce the bug?

Input:

const net = require('net')
let server = net.createServer()
server.listen('/tmp/nonexistent/ipc.sock')

Output (when run as script):

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

Error: listen EACCES: permission denied /tmp/nonexistent/ipc.sock
    at Server.setupListenHandle [as _listen2] (net.js:1272:21)
    at listenInCluster (net.js:1337:12)
    at Server.listen (net.js:1434:5)
    at [stdin]:3:8
    at Script.runInThisContext (vm.js:132:18)
    at Object.runInThisContext (vm.js:309:38)
    at internal/process/execution.js:77:19
    at [stdin]-wrapper:6:22
    at evalScript (internal/process/execution.js:76:60)
    at internal/main/eval_stdin.js:29:5
Emitted 'error' event on Server instance at:
    at emitErrorNT (net.js:1316:8)
    at processTicksAndRejections (internal/process/task_queues.js:80:21) {
  code: 'EACCES',
  errno: -13,
  syscall: 'listen',
  address: '/tmp/nonexistent/ipc.sock',
  port: -1
}

When run directly in the node prompt, the output is different, but the difference is not relevant here.

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

Always reproducible, no conditions

What is the expected behavior?

The error message tells something like "ENOENT: no such file or directory", code and errno show 'ENOENT' and 2 (or maybe -2) respectively.

What do you see instead?

The error message claims that there was a permission denied error (EACCES), which is not the case.

Additional information

Relevant excerpt from strace:

socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 18
bind(18, {sa_family=AF_UNIX, sun_path="/tmp/nonexistent/ipc.sock"}, 110) = -1 ENOENT (No such file or directory)
close(18)

This clearly shows that the OS actually does report ENOENT correctly, but somehow that gets mangled into EACCES.

evanlucas commented 4 years ago

That seems to be explicitly done in libuv (https://github.com/libuv/libuv/blob/a629688008694ed8022269e66826d4d6ec688b83/src/unix/pipe.c#L75-L76) to be compatible with how windows handles this