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

WASI: Crash when terminating a worker thread #33377

Closed
tagesmutter opened this issue May 12, 2020 · 2 comments
Closed

WASI: Crash when terminating a worker thread #33377

tagesmutter opened this issue May 12, 2020 · 2 comments
Labels
wasi Issues and PRs related to the WebAssembly System Interface. worker Issues and PRs related to Worker support.

Comments

@tagesmutter
Copy link

tagesmutter commented May 12, 2020

Version: v14.2.0
Platform: Linux x1 5.6.11-arch1-1 #1 SMP PREEMPT Wed, 06 May 2020 17:32:37 +0000 x86_64 GNU/Linux
Subsystem: WASI, worker_threads

What steps will reproduce the bug?

The idea is that I want to detect long running code in a worker. And terminate the worker after some timeout (3000ms in my case). Everything is working fine for normal JS code in the worker. When I use WASM in my worker nodejs crashes with a fatal error (see stack trace further below)

Here is the minimal test case I could produce:

  1. Create a WASM file by compiling a C++ program with emscripten. The C++ program needs to have a long running task. I used an endless loop:
int main(int argc, char** argv) {
	for(int i=0; i<100; ) {}
	return 0;
}

  1. Load and run the WASM file inside the worker thread. Terminate the worker after some timeout. In the code below the runWASM function is run in the worker thread (by converting it to a string via toString() and setting eval to true in the worker options. The main function is run in the main thread:
async function runWASM(wasmFile) {
	const fs = require('fs').promises
	const { WASI } = require('wasi')
	const wasi = new WASI({
		args: [],
		env: process.env,
		preopens: {},
		returnOnExit: true
	})
	const importObject = { wasi_snapshot_preview1: wasi.wasiImport }

	let buf = await fs.readFile(wasmFile)
	const wasm = await WebAssembly.compile(buf)
	const instance = await WebAssembly.instantiate(wasm, importObject)
	wasi.start(instance)
}

function main() {
	const wt = require("worker_threads")
	let wasmFile = "./program.wasm"	
	let worker = new wt.Worker(`${runWASM.toString()}\nrunWASM("${wasmFile}")`, {eval:true})
	let timeoutId = setTimeout(() => {
		console.log("terminating wasm worker")
		worker.terminate()
	}, 3000)
	console.log("threadId", worker.threadId)
	worker.on("exit", exitCode => {
		clearTimeout(timeoutId) 
		console.log("exited", worker.threadId)
	})
}
main()

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

Always reproducible

What is the expected behavior?

The worker thread is terminated and the main thread continues

What do you see instead?

NodeJS is crashing with

FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal.
 1: 0x55ee3b6e9131 node::Abort() [node]
 2: 0x55ee3b6262ce node::FatalError(char const*, char const*) [node]
 3: 0x55ee3b86aa7b v8::Utils::ReportApiFailure(char const*, char const*) [node]
 4: 0x55ee3b64ddf2 node::EmitBeforeExit(node::Environment*) [node]
 5: 0x55ee3b7ae4ba node::worker::Worker::Run() [node]
 6: 0x55ee3b7ae9c8  [node]
 7: 0x7f4f80af846f  [/usr/lib/libpthread.so.0]
 8: 0x7f4f80a263d3 clone [/usr/lib/libc.so.6]

Additional information

Obviously I am using the experimental WASI interface. I therefore run node with
node --experimental-wasi-unstable-preview1 --experimental-wasm-bigint index.js

@addaleax addaleax added wasi Issues and PRs related to the WebAssembly System Interface. worker Issues and PRs related to Worker support. labels May 12, 2020
@cjihrig
Copy link
Contributor

cjihrig commented May 12, 2020

This appears to be a regression in Node 14. I have similar test cases in my wasi-worker module. They pass on Node 13 - but I just tried on Node 14 and see a similar hard crash.

bnoordhuis added a commit to bnoordhuis/io.js that referenced this issue May 16, 2020
Be careful when emitting the 'beforeExit' event. It's not allowed to
call into the runtime when a termination exception is pending.

Fixes: nodejs#33377
BridgeAR pushed a commit that referenced this issue May 23, 2020
Be careful when emitting the 'beforeExit' event. It's not allowed to
call into the runtime when a termination exception is pending.

Fixes: #33377

PR-URL: #33386
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: James M Snell <[email protected]>
codebytere pushed a commit that referenced this issue Jun 18, 2020
Be careful when emitting the 'beforeExit' event. It's not allowed to
call into the runtime when a termination exception is pending.

Fixes: #33377

PR-URL: #33386
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: James M Snell <[email protected]>
codebytere pushed a commit that referenced this issue Jun 18, 2020
Be careful when emitting the 'beforeExit' event. It's not allowed to
call into the runtime when a termination exception is pending.

Fixes: #33377

PR-URL: #33386
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: James M Snell <[email protected]>
codebytere pushed a commit that referenced this issue Jun 30, 2020
Be careful when emitting the 'beforeExit' event. It's not allowed to
call into the runtime when a termination exception is pending.

Fixes: #33377

PR-URL: #33386
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: James M Snell <[email protected]>
codebytere pushed a commit that referenced this issue Jul 8, 2020
Be careful when emitting the 'beforeExit' event. It's not allowed to
call into the runtime when a termination exception is pending.

Fixes: #33377

PR-URL: #33386
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: James M Snell <[email protected]>
@lukas1994
Copy link

I'm running into a very similar issue in node 14.16.1. I'm using the npm workerpool package and when I try to cancel a worker the whole node process dies with

FATAL ERROR: v8::FromJust Maybe value is Nothing.
1: 0xa04200 node::Abort() [/usr/local/bin/node]
2: 0x94e4e9 node::FatalError(char const*, char const*) [/usr/local/bin/node]
3: 0xb794aa v8::Utils::ReportApiFailure(char const*, char const*) [/usr/local/bin/node]
...
9: 0xabc4a3 node::worker::Worker::Run() [/usr/local/bin/node]
10: 0xabcf28  [/usr/local/bin/node]
11: 0x7efc07120fa3  [/lib/x86_64-linux-gnu/libpthread.so.0]
12: 0x7efc070514cf clone [/lib/x86_64-linux-gnu/libc.so.6]
Aborted (core dumped)
error Command failed with exit code 134

The commit that's supposed to tix this doesn't seem to be merged. Any ideas on how I can resolve this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wasi Issues and PRs related to the WebAssembly System Interface. worker Issues and PRs related to Worker support.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants