Skip to content

Segmentation fault on require("@swc/core") in a Node.js worker thread #2276

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

Closed
andersk opened this issue Sep 20, 2021 · 20 comments
Closed

Segmentation fault on require("@swc/core") in a Node.js worker thread #2276

andersk opened this issue Sep 20, 2021 · 20 comments
Labels
Milestone

Comments

@andersk
Copy link
Contributor

andersk commented Sep 20, 2021

Running require("@swc/core") inside a Node.js worker thread causes a segfault. (This causes problems with terser-webpack-plugin’s new swcMinify function.)

// test.js
const { Worker } = require("worker_threads");
new Worker('require("@swc/core")', { eval: true });
$ node test.js
Segmentation fault (core dumped)

I’m running Node 14.17.6 on Linux x86-64 (NixOS 21.11). In case this is system-dependent, here’s a Dockerfile that should reproduce reliably:

# Dockerfile
FROM node:14.17.6
WORKDIR /tmp
RUN npm i @swc/[email protected]
RUN node -e 'new worker_threads.Worker(`require("@swc/core")`, { eval: true })'
$ docker build .
Sending build context to Docker daemon  57.85MB
Step 1/4 : FROM node:14.17.6
 ---> 9dc0768a6295
Step 2/4 : WORKDIR /tmp
 ---> Using cache
 ---> ade3fef59802
Step 3/4 : RUN npm i @swc/[email protected]
 ---> Using cache
 ---> e1b2d22eae67
Step 4/4 : RUN node -e 'new worker_threads.Worker(`require("@swc/core")`, { eval: true })'
 ---> Running in 25299ad85030
Segmentation fault (core dumped)
The command '/bin/sh -c node -e 'new worker_threads.Worker(`require("@swc/core")`, { eval: true })'' returned a non-zero code: 139
@andersk andersk added the C-bug label Sep 20, 2021
@kdy1
Copy link
Member

kdy1 commented Sep 21, 2021

Native node bindings are expected to

  • Call async operations from js thread

or

  • Call synchronous function from worker thread

It's the limitation of node js itself.

cc @Brooooooklyn
Am I right?

@andersk
Copy link
Contributor Author

andersk commented Sep 21, 2021

I don’t know of any such limitation. Perhaps you’re confusing worker threads (JS threads created using the worker_threads API) with threads in the worker pool (native threads created from addons to perform synchronous operations that are exposed to JS via a custom asynchronous JS API)?

In worker threads, Node.js addons should be able to perform synchronous and asynchronous operations, provided they follow certain rules about thread safety and context awareness.

@Brooooooklyn
Copy link
Member

In worker threads, Node.js addons should be able to perform synchronous and asynchronous operations, provided they follow certain rules about thread safety and context awareness.

Yes. I will dig into this issue today.

@Brooooooklyn
Copy link
Member

This issue only occurs on Linux GNU platform with napi-rs. I've tried Linux musl / macOS / Windows, all these platform is fine.
And I've also tried this example https://github.com/nodejs/node-addon-examples/tree/main/async_pi_estimate/node-addon-api on Linux GNU, also works fine.

I need more time to dig into it.

@kdy1
Copy link
Member

kdy1 commented Dec 16, 2021

Does it happen only on centos?
Maybe it's a bug of glibc in centos 7

@andersk
Copy link
Contributor Author

andersk commented Dec 16, 2021

@kdy1 I originally found this on NixOS 21.11; the node:14.17.6 Docker image is based on Debian 9, and it also reproduces with node:16.13.1 which is based on Debian 10. Since you asked, I was also able to reproduce on CentOS 8.4.2105. As far as I can tell, all glibc platforms are impacted. (Did you find a glibc platform that isn’t?)

@Brooooooklyn
Copy link
Member

Maybe a valid workaround rust-lang/rust#91979 (comment)

@Jackson-p
Copy link

+1,i meet this problem too,it also caused by terser-webpack-plugin’s new swcMinify function.

@Brooooooklyn
Copy link
Member

@Jackson-p What are your system and Glibc versions

@Jackson-p
Copy link

@Jackson-p What are your system and Glibc versions

CentOS Linux release 7.4.1708(Core)

ldd(GNU libc) 2.17

@Brooooooklyn

@Brooooooklyn
Copy link
Member

I've confirmed, this issue should have been fixed in #3314

docker run -w /root --rm -it node:14.17.6 sh -c "npm i @swc/core && node -e 'new worker_threads.Worker(\`console.log(require(\"@swc/core\"))\`, { eval: true })'"
npm WARN saveError ENOENT: no such file or directory, open '/root/package.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @swc/[email protected] (node_modules/@swc/core/node_modules/@swc/core-win32-ia32-msvc):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @swc/[email protected]: wanted {"os":"win32","arch":"ia32"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @swc/[email protected] (node_modules/@swc/core/node_modules/@swc/core-win32-x64-msvc):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @swc/[email protected]: wanted {"os":"win32","arch":"x64"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @swc/[email protected] (node_modules/@swc/core/node_modules/@swc/core-linux-arm-gnueabihf):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @swc/[email protected]: wanted {"os":"linux","arch":"arm"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @swc/[email protected] (node_modules/@swc/core/node_modules/@swc/core-linux-arm64-musl):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @swc/[email protected]: wanted {"os":"linux","arch":"arm64"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @swc/[email protected] (node_modules/@swc/core/node_modules/@swc/core-android-arm64):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @swc/[email protected]: wanted {"os":"android","arch":"arm64"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @swc/[email protected] (node_modules/@swc/core/node_modules/@swc/core-darwin-arm64):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @swc/[email protected]: wanted {"os":"darwin","arch":"arm64"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @swc/[email protected] (node_modules/@swc/core/node_modules/@swc/core-linux-arm64-gnu):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @swc/[email protected]: wanted {"os":"linux","arch":"arm64"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @swc/[email protected] (node_modules/@swc/core/node_modules/@swc/core-win32-arm64-msvc):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @swc/[email protected]: wanted {"os":"win32","arch":"arm64"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @swc/[email protected] (node_modules/@swc/core/node_modules/@swc/core-darwin-x64):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @swc/[email protected]: wanted {"os":"darwin","arch":"x64"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @swc/[email protected] (node_modules/@swc/core/node_modules/@swc/core-android-arm-eabi):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @swc/[email protected]: wanted {"os":"android","arch":"arm"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: @swc/[email protected] (node_modules/@swc/core/node_modules/@swc/core-freebsd-x64):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for @swc/[email protected]: wanted {"os":"freebsd","arch":"x64"} (current: {"os":"linux","arch":"x64"})
npm WARN enoent ENOENT: no such file or directory, open '/root/package.json'
npm WARN root No description
npm WARN root No repository field.
npm WARN root No README data
npm WARN root No license field.

+ @swc/[email protected]
added 3 packages from 1 contributor and audited 14 packages in 68.157s

1 package is looking for funding
  run `npm fund` for details

found 0 vulnerabilities

{
  version: '1.2.133',
  plugins: [Function: plugins],
  Compiler: [class Compiler],
  parse: [Function: parse],
  parseSync: [Function: parseSync],
  parseFile: [Function: parseFile],
  parseFileSync: [Function: parseFileSync],
  print: [Function: print],
  printSync: [Function: printSync],
  transform: [Function: transform],
  transformSync: [Function: transformSync],
  transformFile: [Function: transformFile],
  transformFileSync: [Function: transformFileSync],
  bundle: [Function: bundle],
  minify: [Function: minify],
  minifySync: [Function: minifySync],
  DEFAULT_EXTENSIONS: [
    '.js',  '.jsx',
    '.es6', '.es',
    '.mjs', '.ts',
    '.tsx'
  ]
}

@Brooooooklyn
Copy link
Member

/cc @devongovett since you can use the zig as cross compiling linker to support GLIBC < 2.12, you can avoid the __cxa_thread_atexit_impl issue in rust-lang/rust#91979 . So no more workaround is needed.

@kdy1
Copy link
Member

kdy1 commented Jan 24, 2022

@Brooooooklyn Do you mean this issue can be closed?

@Brooooooklyn
Copy link
Member

Do you mean this issue can be closed?

Yes

@kdy1
Copy link
Member

kdy1 commented Jan 24, 2022

Thank you!

@kdy1 kdy1 closed this as completed Jan 24, 2022
@kdy1 kdy1 added this to the v1.2.133 milestone Jan 24, 2022
@devongovett
Copy link
Contributor

@Brooooooklyn could you explain how this works and how it fixes the Rust issue? Does this mean it doesn't depend on glibc somehow?

@Brooooooklyn
Copy link
Member

@devongovett It is a little complex, I'll write an article to talk about this.

In a nutshell, __cxa_thread_atexit_impl is introduced in std/src/sys/unix/thread_local_dtor.rs#L7-L13

But it's weakly linked since Rust std has a fallback implementation: std/src/sys/unix/thread_local_dtor.rs#L27

If a library is built with target < GLIBC_2.18, the __cxa_thread_atexit_impl symbol will not be linked.

@devongovett
Copy link
Contributor

@Brooooooklyn ah interesting. So if I understand correctly, another solution would be to build on a system (or docker image) with an older glibc version? What kind of magic is zig doing here?

I'll write an article to talk about this.

That would be great!

@Brooooooklyn
Copy link
Member

Brooooooklyn commented Jan 25, 2022

So if I understand correctly, another solution would be to build on a system (or docker image) with an older glibc version?

Yes, we can only compile our codes on an older glibc version system without zig.

If we are using zig as the program linker, we can target our binary to whatever glibc versions, like x86_64-linux-gnu.2.12. So we can build a binary which compatible with an older glibc system on a modern system.

https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html
https://github.com/napi-rs/napi-rs/blob/main/cli/src/build.ts#L279

@swc-bot
Copy link
Collaborator

swc-bot commented Oct 19, 2022

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@swc-project swc-project locked as resolved and limited conversation to collaborators Oct 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

No branches or pull requests

6 participants