-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
Segfaults with dynamic imports and mocha #27492
Comments
I removed most of the external dependencies: only |
Debug backtrace (on
|
With the following diff, we get: https://gist.github.com/targos/7d9d1dc657a322519de758d8b29e9e21 diff --git a/src/module_wrap.cc b/src/module_wrap.cc
index a4e81dcc29..4ffb2534df 100644
--- a/src/module_wrap.cc
+++ b/src/module_wrap.cc
@@ -975,6 +975,7 @@ static MaybeLocal<Promise> ImportModuleDynamically(
ModuleWrap* wrap = ModuleWrap::GetFromID(env, id);
object = wrap->object();
} else if (type == ScriptType::kFunction) {
+ printf("find: %i\n", id);
object = env->id_to_function_map.find(id)->second.Get(iso);
} else {
UNREACHABLE();
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
index f8d43e062e..fdd3d41381 100644
--- a/src/node_contextify.cc
+++ b/src/node_contextify.cc
@@ -289,7 +289,9 @@ void ContextifyContext::WeakCallback(
void ContextifyContext::WeakCallbackCompileFn(
const WeakCallbackInfo<CompileFnEntry>& data) {
CompileFnEntry* entry = data.GetParameter();
+ printf("weakcallback %i\n", entry->id);
if (entry->env->compile_fn_entries.erase(entry) != 0) {
+ printf("erase %i\n", entry->id);
entry->env->id_to_function_map.erase(entry->id);
delete entry;
}
@@ -1110,6 +1112,7 @@ void ContextifyContext::CompileFunction(
return;
}
Local<Function> fn = maybe_fn.ToLocalChecked();
+ printf("emplace %i\n", id);
env->id_to_function_map.emplace(std::piecewise_construct,
std::make_tuple(id),
std::make_tuple(isolate, fn));
|
So, if I understand correctly, the issue is that the main script's ( It can be reproduced immediately after the first import with: diff --git a/build/test/test.esm.js b/build/test/test.esm.js
index ee16ed3..ce3c438 100644
--- a/build/test/test.esm.js
+++ b/build/test/test.esm.js
@@ -1,6 +1,7 @@
(async () => {
console.log("Before imports");
await import("./test/builtins/sint8.spec.mjs");
+ gc();
console.log("Imports: 1");
await import("./test/builtins/uint8.spec.mjs");
console.log("Imports: 2");
diff --git a/run.sh b/run.sh
index aff31ff..8fbaf07 100755
--- a/run.sh
+++ b/run.sh
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
set -ex
-node --experimental-modules --es-module-specifier-resolution=node node_modules/mocha/bin/_mocha build/test/test.esm.js --delay --async --no-config --no-package --no-opts --diff --extension js --reporter spec --slow 75 --timeout 2000 --ui bdd
+node --expose-gc --experimental-modules --es-module-specifier-resolution=node node_modules/mocha/bin/_mocha build/test/test.esm.js --delay --async --no-config --no-package --no-opts --diff --extension js --reporter spec --slow 75 --timeout 2000 --ui bdd |
thanks for looking into this targos. I've been planning a rewrite of module internals to fix a bunch of GC issues, I guess this is just the latest on the pile. |
I too experienced reproduceable segfaults with ESM imports after upgrading lately. I'm not familiar with the NodeJS-source but I managed to narrow it down to something between the versions v10.15.2 (works) and v10.15.3 (segfault). |
This only puts off the inevitable, but I found using this snippet in my mocha loader: (async () => {
const matches = globSync(join(__dirname, "**/*-test.mjs"));
await Promise.all(matches.map(x => import(pathToFileURL(resolve(x)).href)));
run();
})(); lets me get a tiny bit further :) Here's hoping this bug can be fixed as it affects both v10 LTS and v12! |
I was trying to repro this, but it just freezes on the second import line now. cc @targos 'use strict';
(async () => {
await import('./test1.mjs');
console.log('1');
gc();
console.log('gc');
await import('./test2.mjs');
console.log('2');
})(); |
GC behavior probably changed with V8 7.5 |
ok i can reproduce it after #27775 (although there seems to bug in 27775) |
I am testing the new ESM implementation on one of my projects. I am able to consistently get segfaults when using experimental modules and dynamic imports with mocha unit tests.
I extracted a reproducible example to demurgos/node-esm-sigsegv. I am working on reducing the example to be minimal.
The README.md has more details, here is a summary:
You can clone the repo, install the dependencies and run the following command:
The segfault occurs while evaluating the function in test.esm.js.
This function sequentially dynamically imports ESM spec files.
When importing a single file, the execution succeeds.
When importing 2 or 3 files, the execution segfaults 25% of the time.
When importing more files, the execution always segfaults.
I don't know the exact cause of the segfault yet. I am working on isolating it to a minimal example.
It is worth noting that Mocha injects global variables (which may interact badly with ES modules). It may also be a mocha bug, at the moment I am suspecting an ESM issue because it is a C++ crash (and not a JS exception).
The text was updated successfully, but these errors were encountered: