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 inside napi_is_detached_arraybuffer after period of no usage #1610

Open
broken opened this issue Nov 3, 2024 · 5 comments
Open

Crash inside napi_is_detached_arraybuffer after period of no usage #1610

broken opened this issue Nov 3, 2024 · 5 comments

Comments

@broken
Copy link

broken commented Nov 3, 2024

I have an Electron app which uses node-addon-api to retrieve and access a number of objects written in C++. After the app has been running for a long time and not received further usage (typically 12+ hours), it often will crash when I attempt to use it again. I suspect something is being garbage collected (the exported class?) during this period of no usage, so trying to access it later is what causes the crash.

I have collected a number of stack traces, but this is a good one since it should be just calling a static method with an int.

***** FATAL SIGNAL RECEIVED *******
Received fatal signal: SIGSEGV(11)	PID: 48583

***** SIGNAL SIGSEGV(11)

*******	STACKDUMP *******
	stack dump [1]  (anonymous namespace)::signalHandler(int, __siginfo*, void*) + 97
	stack dump [2]  _sigtramp + 29
	stack dump [3]  3   soulsifter.node                     0x0000000110deff00 soulsifter.node + 1474304
	stack dump [4]  PlaylistEntry::findByPlaylistId(Napi::CallbackInfo const&) + 314
	stack dump [5]  napi_value__* Napi::details::TemplatedCallback<&(PlaylistEntry::findByPlaylistId(Napi::CallbackInfo const&))>(napi_env__*, napi_callback_info__*) + 33
	stack dump [6]  6   Electron Framework                  0x0000000119a3deac napi_is_detached_arraybuffer + 396
	stack dump [7]  7   Electron Framework                  0x00000001118d423f Electron Framework + 225855
	stack dump [8]  8   Electron Framework                  0x00000001118d1ea7 Electron Framework + 216743

Exiting after fatal event  (FATAL_SIGNAL). Fatal type:  SIGSEGV

My related code:

Napi::Object PlaylistEntry::Init(Napi::Env env, Napi::Object exports) {
  Napi::Function func = DefineClass(env, "PlaylistEntry", {
    ...
    StaticMethod<&PlaylistEntry::findByPlaylistId>("findByPlaylistId"),
  });

  constructor = new Napi::FunctionReference();
  *constructor = Napi::Persistent(func);

  exports.Set("PlaylistEntry", func);
  return exports;
}


Napi::Value PlaylistEntry::findByPlaylistId(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  if (info.Length() < 1) {
    Napi::TypeError::New(env, "Expected at least 1 argument.").ThrowAsJavaScriptException();
    return env.Null();
  }
  if (!info[0].IsNumber()) {
    Napi::TypeError::New(env, "TypeError: Number expected (for info[0])").ThrowAsJavaScriptException();
    return env.Null();
  }
  int32_t a0(info[0].As<Napi::Number>().Int32Value());
  dogatech::ResultSetIterator<dogatech::soulsifter::PlaylistEntry>* result =
      dogatech::soulsifter::PlaylistEntry::findByPlaylistId(a0);

  vector<dogatech::soulsifter::PlaylistEntry*>* v = result->toVector();
  Napi::Array a = Napi::Array::New(env, static_cast<int>(v->size()));
  for (int i = 0; i < (int) v->size(); i++) {
    Napi::Object instance = PlaylistEntry::NewInstance(env);
    PlaylistEntry* r = Napi::ObjectWrap<PlaylistEntry>::Unwrap(instance);
    r->setWrappedValue((*v)[i], true);
    a.Set(i, instance);
  }
  delete v;
  return a;
}

.. and in the module init file:

Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
...
  PlaylistEntry::Init(env, exports);
...
  return exports;
}

NODE_API_MODULE(soulsifter, InitAll)

Any insight or help would be appreciated, and let me know if you believe this is an issue for Electron instead.
Thanks!

@legendecas
Copy link
Member

napi_is_detached_arraybuffer will not call into userland functions. I think the backtrace might be inaccurate. I guess it will be easier to debug with a coredump.

@broken
Copy link
Author

broken commented Nov 10, 2024

My thought was that the napi_value that napi_is_detached_arraybuffer is checking has been garbage collected, and trying to look at that memory is what is causing the SIGSEGV(11).

I recently experienced a slightly different stackdump which has a v8 call in the mix in case it helps.

******* STACKDUMP *******
        stack dump [1]  (anonymous namespace)::signalHandler(int, __siginfo*, void*) + 97
        stack dump [2]  _sigtramp + 29
        stack dump [3]  3   ???                                 0x00003c71006e7204 0x0 + 66456036209156
        stack dump [4]  Napi::ObjectWrap<Song>::ConstructorCallbackWrapper(napi_env__*, napi_callback_info__*)::'lambda0'()::operator()() const + 67
        stack dump [5]  Napi::ObjectWrap<Song>::ConstructorCallbackWrapper(napi_env__*, napi_callback_info__*) + 88
        stack dump [6]  6   Electron Framework                  0x00000001147ce361 napi_is_detached_arraybuffer + 305
        stack dump [7]  v8::SourceLocation::ToString() const + 170249
        stack dump [8]  v8::SourceLocation::ToString() const + 167675
        stack dump [9]  9   Electron Framework                  0x000000010c5c67b6 Electron Framework + 894902

Honestly, I'm not sure how to get a coredump when I hit this error, since it's happening inside the napi code that was called from javascript.

@legendecas
Copy link
Member

What I meant is that napi_is_detached_arraybuffer will not call into functions like Napi::ObjectWrap<Song>::ConstructorCallbackWrapper, as the frames of [5] and [6] like.

Would you mind sharing the platform you encounter this problem? Windows, or macOS/Linux?

@broken
Copy link
Author

broken commented Nov 13, 2024

Aha, I was reading the stack trace backwards and was thinking it showed Napi::ObjectWrap::ConstructorCallbackWrapper was calling into napi_is_detached_arraybuffer, not the other way around.

macOS monterey 12.7.6
node-addon-api 8.2.1
node-gyp 10.2.0
electron 33.2.0

@mhdawson
Copy link
Member

We discussed in the team meeting today and our suggestion is to try to run under valgrind which might provide some additional info. This doc has some info on doing that:

https://github.com/nodejs/node/blob/main/doc/contributing/investigating-native-memory-leaks.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In Progress
Development

No branches or pull requests

3 participants