Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nodejs can't work #67

Open
zaoqi opened this issue Jun 8, 2019 · 4 comments
Open

nodejs can't work #67

zaoqi opened this issue Jun 8, 2019 · 4 comments

Comments

@zaoqi
Copy link

zaoqi commented Jun 8, 2019

No description provided.

@dex4er
Copy link
Owner

dex4er commented Jun 14, 2019

Probably statx is missing

@hinshun
Copy link

hinshun commented Apr 23, 2020

Hi @dex4er, can you expand what's missing for nodejs to function?

I was able to run node --version, node -e "console.log(1 + 1)" and even node inspect, so clearly some subset of the node runtime is functional. The problem seems to be some internal loader isn't able to load any scripts. For example, npm (which just a wrapper over node /path/to/npm.js) fails with:

 internal/modules/cjs/loader.js:983
   throw err;
   ^

 Error: Cannot find module '/usr/local/bin/npm'
     at Function.Module._resolveFilename (internal/modules/cjs/loader.js:980:15)
     at Function.Module._load (internal/modules/cjs/loader.js:862:27)
     at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)
     at internal/main/run_main_module.js:18:47 {
   code: 'MODULE_NOT_FOUND',
   requireStack: []
 }

@hinshun
Copy link

hinshun commented Apr 30, 2020

For others that are reading this, I found out that nodejs uses libuv, which in turns usually uses glibc wrappers for syscalls. However, a recent change from last year made it start using statx, a relatively new syscall. Fakechroot works by shimming glibc calls using LD_PRELOAD so it can't shim the syscall libuv is calling directly.

So if you want to run nodejs in fakechroot you have three options:

  1. If nodejs is dynamically linked to libuv (via --shared-libuv build flag), then you can patch libuv.
  2. If nodejs is statically linked to libuv (the much more common one), then you have to patch libuv in the nodejs repository, and build node yourself. I built one for node v12.6.2 and I pushed the binary to DockerHub openllb/node:fakechroot for my usage.
  3. The proper way is to contribute to libuv. Glibc 2.28 already had statx support, so we just need to update libuv to that, and then bump libuv in nodejs.

Here's a gist to the git patch I applied, as well as stacktraces on how I determined the fix: https://gist.github.com/hinshun/ba1a8a7d32e8e974dcd60cbce64438d6

@bnoordhuis
Copy link

I also commented on the libuv issue but, while libuv could work around this limitation in fakechroot, it's IMO better to teach it about syscall() - syscall(__NR_statx) in particular.

Libuv also uses syscall() for other things it can't rely on being available from libc:

$ git grep -n 'syscall[(]' src/
src/unix/core.c:531:  return syscall(SYS_close, fd);
src/unix/linux-syscalls.c:136:  return syscall(__NR_sendmmsg, fd, mmsg, vlen, flags);
src/unix/linux-syscalls.c:149:  return syscall(__NR_recvmmsg, fd, mmsg, vlen, flags, timeout);
src/unix/linux-syscalls.c:158:  return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
src/unix/linux-syscalls.c:167:  return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
src/unix/linux-syscalls.c:176:  return syscall(__NR_dup3, oldfd, newfd, flags);
src/unix/linux-syscalls.c:192:  return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf);
src/unix/linux-syscalls.c:201:  return syscall(__NR_getrandom, buf, buflen, flags);
src/unix/random-sysctl-linux.c:71:    if (syscall(SYS__sysctl, &args) == -1)

(SYS_close is used because glibc's close() is a cancellation point.)

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

No branches or pull requests

4 participants