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

Memory leak on macOS when use C++ std::thread #1003

Closed
tianlei124 opened this issue May 21, 2021 · 3 comments
Closed

Memory leak on macOS when use C++ std::thread #1003

tianlei124 opened this issue May 21, 2021 · 3 comments

Comments

@tianlei124
Copy link

I used std::thread in the C++ addon code, and a memory leak is found using LeakTracer.
Here is my C++ addon code:

#include <node_api.h>

#include "leaktracer.h"

namespace demo {

napi_value Method(napi_env env, napi_callback_info args) {
  napi_value greeting;
  napi_status status;
  leaktracer_startMonitoringAllThreads();
  {
      auto t = std::thread([]{ printf("hello"); });
      t.join();
  }
  // std::this_thread::sleep_for(std::chrono::seconds(3));
  status = napi_create_string_utf8(env, "world", NAPI_AUTO_LENGTH, &greeting);
  if (status != napi_ok) return nullptr;
  leaktracer_stopAllMonitoring();
  leaktracer_writeLeaksToFile("./leaks.txt");

  return greeting;
}

napi_value init(napi_env env, napi_value exports) {
  napi_status status;
  napi_value fn;

  status = napi_create_function(env, nullptr, 0, Method, nullptr, &fn);
  if (status != napi_ok) return nullptr;

  status = napi_set_named_property(env, exports, "hello", fn);
  if (status != napi_ok) return nullptr;
  return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, init)

}  // namespace demo

Then js code which invoke addon:

// hello.js
const addon = require('./build/Debug/addon');
console.log(addon.hello());
// Prints: 'world'

The backtrace of leak is :
leaktracer::MemoryTrace::registerAllocation(void*, unsigned long, bool);operator new(unsigned long);std::__1::thread::thread<demo::Method(napi_env__*, napi_callback_info__*)::$_0, void>(demo::Method(napi_env__*, napi_callback_info__*)::$_0&&);std::__1::thread::thread<demo::Method(napi_env__*, napi_callback_info__*)::$_0, void>(demo::Method(napi_env__*, napi_callback_info__*)::$_0&&);demo::Method(napi_env__*, napi_callback_info__*);(anonymous namespace)::v8impl::FunctionCallbackWrapper::Invoke(v8::FunctionCallbackInfo<v8::Value> const&);v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo*);v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8;v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::internal::Isolate*)

I have tested on Windows10, Debian9, macOS10.15(Intel CPU) macOS11.3(M1), only macOS has leak.
Does anyone know why this is?

@mhdawson
Copy link
Member

Vladimir mentioned that he has seen something like this as newer thread implementations use pooling so that when the thread completes it is not necessary released.

You could try starting/stopping many threads (say 1000 times) and validate that after some number it does not show additional leaks.

We don't think this is related to node-addon-api at all, the same could outside an addon should report the same thing.

@vmoroz
Copy link
Member

vmoroz commented May 21, 2021

Please see the related discussion on the Android NDK: android/ndk#819

@tianlei124
Copy link
Author

Thanks a lot, I understand.

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

No branches or pull requests

3 participants