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

Crash when used with worker threads #1365

Closed
mohd-akram opened this issue Jul 26, 2020 · 3 comments · Fixed by #1367
Closed

Crash when used with worker threads #1365

mohd-akram opened this issue Jul 26, 2020 · 3 comments · Fixed by #1367

Comments

@mohd-akram
Copy link
Contributor

The following code will crash:

const { isMainThread, Worker } = require('worker_threads');
const sqlite3 = require('sqlite3');
if (isMainThread) new Worker(__filename);
function main() {
  const db = new sqlite3.Database(':memory:');
  db.serialize(() => {
    db.run('CREATE TABLE lorem (info TEXT)');
    while (true) {
      const stmt = db.prepare('INSERT INTO lorem VALUES (?)');
      stmt.finalize();
    }
  });
  db.close();
}
main();

Trace:

FATAL ERROR: Error::ThrowAsJavaScriptException napi_throw
 1: 0x100a59d5d node::Abort() (.cold.1) [/opt/local/bin/node]
 2: 0x100085ca7 node::FatalError(char const*, char const*) [/opt/local/bin/node]
 3: 0x100085e10 node::OnFatalError(char const*, char const*) [/opt/local/bin/node]
 4: 0x100085cb0 node::OnFatalError(char const*, char const*) [/opt/local/bin/node]
 5: 0x100061f67 napi_open_callback_scope [/opt/local/bin/node]
 6: 0x10457118a Napi::Error::Fatal(char const*, char const*) [/Users/mohamed/Downloads/node-sqlite3/lib/binding/napi-v3-darwin-x64/node_sqlite3.node]
 7: 0x10457457d Napi::Error::ThrowAsJavaScriptException() const [/Users/mohamed/Downloads/node-sqlite3/lib/binding/napi-v3-darwin-x64/node_sqlite3.node]
 8: 0x104588247 node_sqlite3::Statement::Statement(Napi::CallbackInfo const&) [/Users/mohamed/Downloads/node-sqlite3/lib/binding/napi-v3-darwin-x64/node_sqlite3.node]
 9: 0x104592b86 Napi::ObjectWrap<node_sqlite3::Statement>::ConstructorCallbackWrapper(napi_env__*, napi_callback_info__*)::'lambda'()::operator()() const [/Users/mohamed/Downloads/node-sqlite3/lib/binding/napi-v3-darwin-x64/node_sqlite3.node]
10: 0x104592900 Napi::ObjectWrap<node_sqlite3::Statement>::ConstructorCallbackWrapper(napi_env__*, napi_callback_info__*) [/Users/mohamed/Downloads/node-sqlite3/lib/binding/napi-v3-darwin-x64/node_sqlite3.node]
11: 0x10004f7f1 v8impl::(anonymous namespace)::FunctionCallbackWrapper::Invoke(v8::FunctionCallbackInfo<v8::Value> const&) [/opt/local/bin/node]
12: 0x1001dca35 v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo) [/opt/local/bin/node]
13: 0x1001dbe15 v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<true>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) [/opt/local/bin/node]
14: 0x1001db8dd v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::internal::Isolate*) [/opt/local/bin/node]
15: 0x100781fd9 Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit [/opt/local/bin/node]
16: 0x100716921 Builtins_JSBuiltinsConstructStub [/opt/local/bin/node]
Abort trap: 6

The culprit seems to be the HasInstance method of Database which is called in Statement::Statement. The constructor that it's checking against isn't context-specific. The issue is fixed when the HasInstance check is removed. I'm not sure how it can be replaced with a context-aware version.

@jschlight

@mightypenguin
Copy link

I'm using threads.js with sqlite3 (through knex) inside a worker thread and it's working fine for me so far.
I had a similar error message when using sqlite3 < v5 and Nodejs 14.

@mohd-akram
Copy link
Contributor Author

I came across the issue on FreeBSD when running an application that uses worker threads, which worked fine on my Mac. I had to put the db.prepare in a loop so that it would also trigger on macOS. So it seems that you can get away with it (especially if you only use sqlite3 in one thread), but I believe there is still a bug here. What happens when you run the code snippet above?

@jschlight
Copy link
Collaborator

The code above crashes on my macOS development system. The issue is the following Database declaration in database.h:

static Napi::FunctionReference constructor;

Static data like this is not supported in a multi-threaded environment

Multi-threaded support is a fairly recent addition to N-API. I've been able to address this issue on my development system using the napi_set_instance_data and napi_get_instance_data API calls to associate a unique constructor value with each thread environment.

These API calls are are implemented in N-APi version 6 and available in Node.js v10.20.0+, v12.8.0+, and v14.0.0+. They are still marked as experimental in the N-API documentation but I've been able to access them without the NAPI_EXPERIMENTAL flag.

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

Successfully merging a pull request may close this issue.

3 participants