Skip to content

Segfault when using node-addon-api Objects during AsyncWorker::Execute #281

Closed

Description

@webern

In the following project:

https://github.com/bitflip-software/xlsx-util/tree/feature/async-worker
branch feature/async-worker
f3b31420281e5f5939ad082c6835f024c14cd728

When I run the project's test with npm run test, I get a segfault.

I've been chasing this down for days, and today I built Node from source (v9.8) so that I could debug.

It appears that all of the objects my code is operating on are being destroyed when uv__fs_done is called, which calls the suspicious looking node::InternalCallbackScope::Close()

But my code is still running on another thread, which ends in tears.

image

My AsyncWorker looks like this

#include "AsyncReader.h"
#include "XlsxReaderFunctions.h"

namespace xlsx
{
    AsyncReader::AsyncReader( Napi::HandleScope scope, const std::string& filename, bool hasHeaders, const Napi::Function& headerTransform, const Napi::Function& callback )
    : Napi::AsyncWorker{ callback }
    , myScope{ scope }
    , myFilename{ filename }
    , myHasHeaders{ hasHeaders }
    , myHeaderTransform{ headerTransform }
    , myResult{}
    {

    }


    void
    AsyncReader::Execute()
    {
        myResult = extractAllData( myScope, myFilename, myHasHeaders, myHeaderTransform );
    }


    void
    AsyncReader::OnOK()
    {
        Callback().MakeCallback( Receiver().Value(), { myScope.Env().Null(), myResult } );
    }


    void
    AsyncReader::OnError( const Napi::Error& e )
    {
        Callback().MakeCallback( Receiver().Value(), { e.Value(), myScope.Env().Undefined() } );
    }
}

The AsyncReader is instantiated and queued like this:

#include "napi.h"
#include "readXlsxAsync.h"
#include "AsyncReader.h"
#include "AsyncError.h"

namespace xlsx
{
    void readXlsxAsync( const Napi::CallbackInfo& info )
    {
        Napi::Env env = info.Env();
        Napi::HandleScope scope{ env };

        // we need to check for the presence of a client callback function
        // and if we do not have one then we must raise a synchronous error
        if( info.Length() != 4 )
        {
            Napi::TypeError::New(env, "invalid argument count").ThrowAsJavaScriptException();
            return;
        }

        if( !info[3].IsFunction() )
        {
            Napi::TypeError::New(env, "invalid callback function [arg3]").ThrowAsJavaScriptException();
            return;
        }

        Napi::Function cb = info[3].As<Napi::Function>();

        if( !info[0].IsString() )
        {
            auto err = new AsyncError{ cb, "first argument must be a string [filename]" };
            err->Queue();
            return;
        }

        if( !info[1].IsBoolean() )
        {
            auto err = new AsyncError{ cb, "second argument must be a bool [hasHeaders]" };
            err->Queue();
            return;
        }

        if( !info[2].IsFunction() )
        {
            auto err = new AsyncError{ cb, "third argument must be a function [headerTransform]" };
            err->Queue();
            return;
        }

        const std::string filename = info[0].As<Napi::String>().Utf8Value();
        const bool hasHeaders = info[1].As<Napi::Boolean>();
        Napi::Function headerTransform = info[2].As<Napi::Function>();
        AsyncReader* reader = new AsyncReader{ scope, filename, hasHeaders, headerTransform, cb };
        reader->Queue();
    }
}

xlsx::extractAllData runs synchronously on a single thread (as far as I understand, though it does create Napi::Objects.

Bottom line, I can't understand why my code segfaults because the lifetime management of these libraries is very complicated and I'm new to this (and Napi:: doesn't seem to have much documentation).

When does an AsyncWorker destroy itself exactly? Can anyone tell me why my code segfaults?

Activity

  1. mhdawson commented on Jun 13, 2018

    @mhdawson
    Member

    Which version of Node.js are you using? Can you also add the full strack trace you get when it crashes ?

  2. mhdawson commented on Jun 13, 2018

    @mhdawson
    Member

    Also, do you run napi, or JS code from Execute() ? Our doc was not clear enough on the C side, PR to clarify is here: nodejs/node#21217. I'd have to double check but I expect the same will apply in the Execute() method for the async worker.

  3. webern commented on Jun 13, 2018

    @webern
    Author

    The production Node build is 9.8.0 but I also segfault in the version of Node that I build with Xcode for debugging, which is 9.11.3.

    The napi version is

        "node-addon-api": {
          "version": "1.3.0",
          "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.3.0.tgz",
          "integrity": "sha512-yagD4yKkZLeG4EJkh+8Qbqhqw+owDQ/PowqD8vb5a5rfNXS/PRC21SGyIbUVXfPp/jl4s+jyeZj6xnLnDPLazw==",
          "dev": true
        },
    

    The backtrace is:

    �[1m�[2mDetermining test suites to run...�[1m�[22m�[999D�[K
    
    �[K
    �[1A
    �[0m�[7m�[33m�[1m RUNS �[22m�[39m�[27m�[0m �[1m...�[22m
    AsyncReader constructor call
    begin getDataAsync
    about to call extractAllRows from getDataAsync
    begin extractAllRows
    
    
    #
    # Fatal error in /Users/mjb/repos/node/deps/v8/src/execution.cc, line 107
    # Check failed: AllowJavascriptExecution::IsAllowed(isolate).
    #
    (lldb) thread backtrace all
    xlsx.node was compiled with optimization - stepping may behave oddly; variables may not be available.
    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
      * frame #0: 0x0000000101ad8991 node`v8::base::OS::Abort() at platform-posix.cc:248
        frame #1: 0x0000000101ad0de7 node`V8_Fatal(file="/Users/mjb/repos/node/deps/v8/src/execution.cc", line=107, format="Check failed: %s.") at logging.cc:126
        frame #2: 0x0000000100e2ae83 node`v8::internal::(anonymous namespace)::Invoke(isolate=0x0000000109004e00, is_construct=false, target=Handle<v8::internal::Object> @ 0x00007ffeefbf1be0, receiver=Handle<v8::internal::Object> @ 0x00007ffeefbf1bd8, argc=2, args=0x0000000107100b70, new_target=Handle<v8::internal::Object> @ 0x00007ffeefbf1bd0, message_handling=kReport) at execution.cc:107
        frame #3: 0x0000000100e2a9b4 node`v8::internal::(anonymous namespace)::CallInternal(isolate=0x0000000109004e00, callable=Handle<v8::internal::Object> @ 0x00007ffeefbf1c90, receiver=Handle<v8::internal::Object> @ 0x00007ffeefbf1c88, argc=2, argv=0x0000000107100b70, message_handling=kReport) at execution.cc:181
        frame #4: 0x0000000100e2a876 node`v8::internal::Execution::Call(isolate=0x0000000109004e00, callable=Handle<v8::internal::Object> @ 0x00007ffeefbf1ce0, receiver=Handle<v8::internal::Object> @ 0x00007ffeefbf1cd8, argc=2, argv=0x0000000107100b70) at execution.cc:191
        frame #5: 0x000000010111b38a node`v8::internal::ErrorUtils::FormatStackTrace(isolate=0x0000000109004e00, error=Handle<v8::internal::JSObject> @ 0x00007ffeefbf1f30, raw_stack=Handle<v8::internal::Object> @ 0x00007ffeefbf1f28) at messages.cc:975
        frame #6: 0x00000001004a8e50 node`v8::internal::Accessors::ErrorStackGetter(key=(val_ = 0x00007ffeefbf2730), info=0x00007ffeefbf2130) at accessors.cc:1164
        frame #7: 0x0000000101006f81 node`v8::internal::PropertyCallbackArguments::Call(this=0x00007ffeefbf2308, f=(node`v8::internal::Accessors::ErrorStackGetter(v8::Local<v8::Name>, v8::PropertyCallbackInfo<v8::Value> const&) at accessors.cc:1141), name=Handle<v8::internal::Name> @ 0x00007ffeefbf21a0)(v8::Local<v8::Name>, v8::PropertyCallbackInfo<v8::Value> const&), v8::internal::Handle<v8::internal::Name>) at api-arguments-inl.h:44
        frame #8: 0x000000010115e14b node`v8::internal::Object::GetPropertyWithAccessor(it=0x00007ffeefbf24c8) at objects.cc:1510
        frame #9: 0x000000010115d084 node`v8::internal::Object::GetProperty(it=0x00007ffeefbf24c8) at objects.cc:1053
        frame #10: 0x0000000101436f7c node`v8::internal::Runtime::GetObjectProperty(isolate=0x0000000109004e00, object=Handle<v8::internal::Object> @ 0x00007ffeefbf2560, key=Handle<v8::internal::Object> @ 0x00007ffeefbf2558, is_found_out=0x0000000000000000) at runtime-object.cc:34
        frame #11: 0x000000010143a9bc node`v8::internal::__RT_impl_Runtime_GetProperty(args=Arguments @ 0x00007ffeefbf2600, isolate=0x0000000109004e00) at runtime-object.cc:439
        frame #12: 0x000000010143a5d0 node`v8::internal::Runtime_GetProperty(args_length=2, args_object=0x00007ffeefbf2738, isolate=0x0000000109004e00) at runtime-object.cc:432
        frame #13: 0x000023b2a57043c4
        frame #14: 0x000023b2a5851fb0
        frame #15: 0x000023b2a57f14ff
        frame #16: 0x000023b2a570569f
        frame #17: 0x000023b2a57f14ff
        frame #18: 0x000023b2a5704259
        frame #19: 0x000023b2a5704101
        frame #20: 0x0000000100e2b065 node`v8::internal::(anonymous namespace)::Invoke(isolate=0x0000000109004e00, is_construct=false, target=Handle<v8::internal::Object> @ 0x00007ffeefbf2b70, receiver=Handle<v8::internal::Object> @ 0x00007ffeefbf2b68, argc=4, args=0x00007ffeefbf2f00, new_target=Handle<v8::internal::Object> @ 0x00007ffeefbf2b60, message_handling=kReport) at execution.cc:145
        frame #21: 0x0000000100e2a9b4 node`v8::internal::(anonymous namespace)::CallInternal(isolate=0x0000000109004e00, callable=Handle<v8::internal::Object> @ 0x00007ffeefbf2c20, receiver=Handle<v8::internal::Object> @ 0x00007ffeefbf2c18, argc=4, argv=0x00007ffeefbf2f00, message_handling=kReport) at execution.cc:181
        frame #22: 0x0000000100e2a876 node`v8::internal::Execution::Call(isolate=0x0000000109004e00, callable=Handle<v8::internal::Object> @ 0x00007ffeefbf2c70, receiver=Handle<v8::internal::Object> @ 0x00007ffeefbf2c68, argc=4, argv=0x00007ffeefbf2f00) at execution.cc:191
        frame #23: 0x00000001004e115e node`v8::Function::Call(this=0x000000010905e3a0, context=(val_ = 0x000000010905dec0), recv=(val_ = 0x000000010913b560), argc=4, argv=0x00007ffeefbf2f00) at api.cc:5384
        frame #24: 0x00000001000135cf node`node::AsyncWrap::EmitAsyncInit(env=0x00007ffeefbfdea0, object=(val_ = 0x000000010913b560), type=(val_ = 0x000000010904fa78), async_id=246, trigger_async_id=243) at async_wrap.cc:710
        frame #25: 0x000000010000c36f node`node::AsyncWrap::AsyncReset(this=0x0000000107056f50, execution_async_id=-1, silent=false) at async_wrap.cc:679
        frame #26: 0x00000001000103da node`node::AsyncWrap::AsyncWrap(this=0x0000000107056f50, env=0x00007ffeefbfdea0, object=(val_ = 0x000000010904dae0), provider=PROVIDER_PROMISE, execution_async_id=-1, silent=false) at async_wrap.cc:618
        frame #27: 0x000000010001431f node`node::PromiseWrap::PromiseWrap(this=0x0000000107056f50, env=0x00007ffeefbfdea0, object=(val_ = 0x000000010904dae0), silent=false) at async_wrap.cc:230
        frame #28: 0x0000000100007344 node`node::PromiseWrap::PromiseWrap(this=0x0000000107056f50, env=0x00007ffeefbfdea0, object=(val_ = 0x000000010904dae0), silent=false) at async_wrap.cc:230
        frame #29: 0x00000001000070d9 node`node::PromiseWrap::New(env=0x00007ffeefbfdea0, promise=(val_ = 0x00007ffeefbf4418), parent_wrap=0x0000000104f10dc0, silent=false) at async_wrap.cc:262
        frame #30: 0x0000000100015730 node`node::PromiseHook(type=kInit, promise=(val_ = 0x00007ffeefbf4418), parent=(val_ = 0x00007ffeefbf4410), arg=0x00007ffeefbfdea0) at async_wrap.cc:303
        frame #31: 0x0000000100039320 node`node::Environment::EnvPromiseHook(type=kInit, promise=(val_ = 0x00007ffeefbf4418), parent=(val_ = 0x00007ffeefbf4410)) at env.cc:289
        frame #32: 0x00000001010c041c node`v8::internal::Isolate::RunPromiseHook(this=0x0000000109004e00, type=kInit, promise=Handle<v8::internal::JSPromise> @ 0x00007ffeefbf4268, parent=Handle<v8::internal::Object> @ 0x00007ffeefbf4260) at isolate.cc:3379
        frame #33: 0x0000000101459549 node`v8::internal::__RT_impl_Runtime_PromiseHookInit(args=Arguments @ 0x00007ffeefbf42e8, isolate=0x0000000109004e00) at runtime-promise.cc:137
        frame #34: 0x0000000101459180 node`v8::internal::Runtime_PromiseHookInit(args_length=2, args_object=0x00007ffeefbf4418, isolate=0x0000000109004e00) at runtime-promise.cc:132
        frame #35: 0x000023b2a57043c4
        frame #36: 0x000023b2a57ea249
        frame #37: 0x000023b2a57f14ff
        frame #38: 0x000023b2a57f14ff
        frame #39: 0x000023b2a570569f
        frame #40: 0x000023b2a579e872
        frame #41: 0x000023b2a579d909
        frame #42: 0x000023b2a585f9cb
        frame #43: 0x000023b2a57f14ff
        frame #44: 0x000023b2a57f14ff
        frame #45: 0x000023b2a570569f
        frame #46: 0x000023b2a57aa9da
        frame #47: 0x000023b2a5704259
        frame #48: 0x000023b2a5704101
        frame #49: 0x0000000100e2b065 node`v8::internal::(anonymous namespace)::Invoke(isolate=0x0000000109004e00, is_construct=false, target=Handle<v8::internal::Object> @ 0x00007ffeefbf4b20, receiver=Handle<v8::internal::Object> @ 0x00007ffeefbf4b18, argc=5, args=0x00007ffeefbf4da0, new_target=Handle<v8::internal::Object> @ 0x00007ffeefbf4b10, message_handling=kReport) at execution.cc:145
        frame #50: 0x0000000100e2a9b4 node`v8::internal::(anonymous namespace)::CallInternal(isolate=0x0000000109004e00, callable=Handle<v8::internal::Object> @ 0x00007ffeefbf4bd0, receiver=Handle<v8::internal::Object> @ 0x00007ffeefbf4bc8, argc=5, argv=0x00007ffeefbf4da0, message_handling=kReport) at execution.cc:181
        frame #51: 0x0000000100e2b2d8 node`v8::internal::Execution::TryCall(isolate=0x0000000109004e00, callable=Handle<v8::internal::Object> @ 0x00007ffeefbf4ca0, receiver=Handle<v8::internal::Object> @ 0x00007ffeefbf4c98, argc=5, args=0x00007ffeefbf4da0, message_handling=kReport, exception_out=0x00007ffeefbf4ec8) at execution.cc:233
        frame #52: 0x00000001010c0a9e node`v8::internal::Isolate::PromiseReactionJob(this=0x0000000109004e00, info=Handle<v8::internal::PromiseReactionJobInfo> @ 0x00007ffeefbf4d98, result=0x00007ffeefbf4ed0, maybe_exception=0x00007ffeefbf4ec8) at isolate.cc:3436
        frame #53: 0x00000001010c19fb node`v8::internal::Isolate::RunMicrotasksInternal(this=0x0000000109004e00) at isolate.cc:3509
        frame #54: 0x00000001010bfc49 node`v8::internal::Isolate::RunMicrotasks(this=0x0000000109004e00) at isolate.cc:3489
        frame #55: 0x00000001004fbab0 node`v8::Isolate::RunMicrotasks(this=0x0000000109004e00) at api.cc:8910
        frame #56: 0x0000000100066673 node`node::InternalCallbackScope::Close(this=0x00007ffeefbf51f0) at node.cc:1300
        frame #57: 0x0000000100066edf node`node::InternalMakeCallback(env=0x00007ffeefbfdea0, recv=(val_ = 0x000000010905fb00), callback=(val_ = 0x000000010904da50), argc=1, argv=0x00007ffeefbf56e0, asyncContext=(async_id = 90, trigger_async_id = 8)) at node.cc:1351
        frame #58: 0x00000001000137dd node`node::AsyncWrap::MakeCallback(this=0x0000000104f103c0, cb=(val_ = 0x000000010904da50), argc=1, argv=0x00007ffeefbf56e0) at async_wrap.cc:720
        frame #59: 0x000000010001fdd7 node`node::AsyncWrap::MakeCallback(this=0x0000000104f103c0, symbol=(val_ = 0x000000010904f700), argc=1, argv=0x00007ffeefbf56e0) at async_wrap-inl.h:54
        frame #60: 0x00000001000cfedc node`node::(anonymous namespace)::After(req=0x0000000104f10400) at node_file.cc:333
        frame #61: 0x000000010172429a node`uv__fs_done(w=0x0000000104f10550, status=0) at fs.c:1129
        frame #62: 0x000000010171c085 node`uv__work_done(handle=0x0000000102a7a7b8) at threadpool.c:251
        frame #63: 0x0000000101720b32 node`uv__async_io(loop=0x0000000102a7a6f0, w=0x0000000102a7a960, events=1) at async.c:118
        frame #64: 0x000000010174006c node`uv__io_poll(loop=0x0000000102a7a6f0, timeout=-1) at kqueue.c:343
        frame #65: 0x000000010172120f node`uv_run(loop=0x0000000102a7a6f0, mode=UV_RUN_DEFAULT) at core.c:368
        frame #66: 0x0000000100082749 node`node::Start(isolate=0x0000000109004e00, isolate_data=0x00007ffeefbfe630, argc=6, argv=0x0000000107235ef0, exec_argc=0, exec_argv=0x0000000107234040) at node.cc:4814
        frame #67: 0x00000001000770d6 node`node::Start(event_loop=0x0000000102a7a6f0, argc=6, argv=0x0000000107235ef0, exec_argc=0, exec_argv=0x0000000107234040) at node.cc:4885
        frame #68: 0x0000000100076785 node`node::Start(argc=6, argv=0x0000000107235ef0) at node.cc:4942
        frame #69: 0x000000010000199e node`main(argc=6, argv=0x00007ffeefbfeeb0) at node_main.cc:124
        frame #70: 0x0000000100001934 node`start + 52
      thread #2
        frame #0: 0x00007fff65f1aa1e libsystem_kernel.dylib`__psynch_cvwait + 10
        frame #1: 0x0000000104d595d9 libsystem_pthread.dylib`_pthread_cond_wait + 732
        frame #2: 0x00000001017374bd node`uv_cond_wait(cond=0x00000001072361b0, mutex=0x0000000107236170) at thread.c:641
        frame #3: 0x000000010012040d node`node::LibuvMutexTraits::cond_wait(cond=0x00000001072361b0, mutex=0x0000000107236170) at node_mutex.h:98
        frame #4: 0x00000001001203e0 node`node::ConditionVariableBase<node::LibuvMutexTraits>::Wait(this=0x00000001072361b0, scoped_lock=0x0000700001839b10) at node_mutex.h:136
        frame #5: 0x000000010011fdaf node`node::TaskQueue<v8::Task>::BlockingPop(this=0x0000000107236170) at node_platform.cc:314
        frame #6: 0x0000000100118b33 node`node::BackgroundRunner(data=0x0000000107236170) at node_platform.cc:21
        frame #7: 0x0000000104d58665 libsystem_pthread.dylib`_pthread_body + 340
        frame #8: 0x0000000104d58511 libsystem_pthread.dylib`_pthread_start + 377
        frame #9: 0x0000000104d57bfd libsystem_pthread.dylib`thread_start + 13
      thread #3
        frame #0: 0x00007fff65f1aa1e libsystem_kernel.dylib`__psynch_cvwait + 10
        frame #1: 0x0000000104d595d9 libsystem_pthread.dylib`_pthread_cond_wait + 732
        frame #2: 0x00000001017374bd node`uv_cond_wait(cond=0x00000001072361b0, mutex=0x0000000107236170) at thread.c:641
        frame #3: 0x000000010012040d node`node::LibuvMutexTraits::cond_wait(cond=0x00000001072361b0, mutex=0x0000000107236170) at node_mutex.h:98
        frame #4: 0x00000001001203e0 node`node::ConditionVariableBase<node::LibuvMutexTraits>::Wait(this=0x00000001072361b0, scoped_lock=0x000070000203cb10) at node_mutex.h:136
        frame #5: 0x000000010011fdaf node`node::TaskQueue<v8::Task>::BlockingPop(this=0x0000000107236170) at node_platform.cc:314
        frame #6: 0x0000000100118b33 node`node::BackgroundRunner(data=0x0000000107236170) at node_platform.cc:21
        frame #7: 0x0000000104d58665 libsystem_pthread.dylib`_pthread_body + 340
        frame #8: 0x0000000104d58511 libsystem_pthread.dylib`_pthread_start + 377
        frame #9: 0x0000000104d57bfd libsystem_pthread.dylib`thread_start + 13
      thread #4
        frame #0: 0x00007fff65f1aa1e libsystem_kernel.dylib`__psynch_cvwait + 10
        frame #1: 0x0000000104d595d9 libsystem_pthread.dylib`_pthread_cond_wait + 732
        frame #2: 0x00000001017374bd node`uv_cond_wait(cond=0x00000001072361b0, mutex=0x0000000107236170) at thread.c:641
        frame #3: 0x000000010012040d node`node::LibuvMutexTraits::cond_wait(cond=0x00000001072361b0, mutex=0x0000000107236170) at node_mutex.h:98
        frame #4: 0x00000001001203e0 node`node::ConditionVariableBase<node::LibuvMutexTraits>::Wait(this=0x00000001072361b0, scoped_lock=0x000070000283fb10) at node_mutex.h:136
        frame #5: 0x000000010011fdaf node`node::TaskQueue<v8::Task>::BlockingPop(this=0x0000000107236170) at node_platform.cc:314
        frame #6: 0x0000000100118b33 node`node::BackgroundRunner(data=0x0000000107236170) at node_platform.cc:21
        frame #7: 0x0000000104d58665 libsystem_pthread.dylib`_pthread_body + 340
        frame #8: 0x0000000104d58511 libsystem_pthread.dylib`_pthread_start + 377
        frame #9: 0x0000000104d57bfd libsystem_pthread.dylib`thread_start + 13
      thread #5
        frame #0: 0x00007fff65f1aa1e libsystem_kernel.dylib`__psynch_cvwait + 10
        frame #1: 0x0000000104d595d9 libsystem_pthread.dylib`_pthread_cond_wait + 732
        frame #2: 0x00000001017374bd node`uv_cond_wait(cond=0x00000001072361b0, mutex=0x0000000107236170) at thread.c:641
        frame #3: 0x000000010012040d node`node::LibuvMutexTraits::cond_wait(cond=0x00000001072361b0, mutex=0x0000000107236170) at node_mutex.h:98
        frame #4: 0x00000001001203e0 node`node::ConditionVariableBase<node::LibuvMutexTraits>::Wait(this=0x00000001072361b0, scoped_lock=0x0000700003042b10) at node_mutex.h:136
        frame #5: 0x000000010011fdaf node`node::TaskQueue<v8::Task>::BlockingPop(this=0x0000000107236170) at node_platform.cc:314
        frame #6: 0x0000000100118b33 node`node::BackgroundRunner(data=0x0000000107236170) at node_platform.cc:21
        frame #7: 0x0000000104d58665 libsystem_pthread.dylib`_pthread_body + 340
        frame #8: 0x0000000104d58511 libsystem_pthread.dylib`_pthread_start + 377
        frame #9: 0x0000000104d57bfd libsystem_pthread.dylib`thread_start + 13
      thread #7
        frame #0: 0x00007fff65f1b292 libsystem_kernel.dylib`__workq_kernreturn + 10
        frame #1: 0x0000000104d5800d libsystem_pthread.dylib`_pthread_wqthread + 1035
        frame #2: 0x0000000104d57bed libsystem_pthread.dylib`start_wqthread + 13
      thread #9
        frame #0: 0x00007fff65f11246 libsystem_kernel.dylib`semaphore_wait_trap + 10
        frame #1: 0x0000000101737277 node`uv_sem_wait(sem=0x0000000102a6cd38) at thread.c:397
        frame #2: 0x00000001001db688 node`node::inspector::(anonymous namespace)::StartIoThreadMain(unused=0x0000000000000000) at inspector_agent.cc:79
        frame #3: 0x0000000104d58665 libsystem_pthread.dylib`_pthread_body + 340
        frame #4: 0x0000000104d58511 libsystem_pthread.dylib`_pthread_start + 377
        frame #5: 0x0000000104d57bfd libsystem_pthread.dylib`thread_start + 13
      thread #10
        frame #0: 0x000000010a8ab6de xlsx.node`shared_strings_callback_find_shared_string_start(callbackdata=0x000070000384aae8, name="t", atts=0x0000000107402530) at xlsxio_read_sharedstrings.c:168 [opt]
        frame #1: 0x000000010a8b38e4 xlsx.node`doContent(parser=0x00000001074017f0, startTagLevel=<unavailable>, enc=<unavailable>, s=<unavailable>, end="", nextPtr=0x0000000107401820, haveMore='\0') at xmlparse.c:2756 [opt]
        frame #2: 0x000000010a8b1b3b xlsx.node`contentProcessor(parser=0x00000001074017f0, start=<unavailable>, end=<unavailable>, endPtr=<unavailable>) at xmlparse.c:2418 [opt]
        frame #3: 0x000000010a8b12d7 xlsx.node`doProlog(parser=<unavailable>, enc=<unavailable>, s=<unavailable>, end="", tok=<unavailable>, next="", nextPtr=0x0000000107401820, haveMore='\0') at xmlparse.c:4366 [opt]
        frame #4: 0x000000010a8af38f xlsx.node`prologProcessor(parser=0x00000001074017f0, s="<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n<sst xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" count=\"4\" uniqueCount=\"4\"><si><t>Hello</t></si><si><t>World</t></si><si><t>pp</t></si><si><t>or</t></si></sst>", end="", nextPtr=0x0000000107401820) at xmlparse.c:4089 [opt]
        frame #5: 0x000000010a8aed6b xlsx.node`XML_ParseBuffer(parser=0x00000001074017f0, len=238, isFinal=1) at xmlparse.c:1915 [opt]
        frame #6: 0x000000010a8a94c2 xlsx.node`expat_process_zip_file(zip=0x0000000104e11950, filename=<unavailable>, start_handler=<unavailable>, end_handler=<unavailable>, data_handler=0x0000000000000000, callbackdata=<unavailable>, xmlparser=0x000070000384aae8) at xlsxio_read.c:155 [opt]
        frame #7: 0x000000010a8aacb2 xlsx.node`xlsxioread_process(handle=0x0000000104e06810, sheetname=<unavailable>, flags=129, cell_callback=0x0000000000000000, row_callback=0x0000000000000000, callbackdata=0x000000010705cfe0) at xlsxio_read.c:1223 [opt]
        frame #8: 0x000000010a8ab08e xlsx.node`xlsxioread_sheet_open(handle=0x0000000104e06810, sheetname=0x0000000000000000, flags=<unavailable>) at xlsxio_read.c:1350 [opt]
        frame #9: 0x000000010a8a5b62 xlsx.node`xlsx::extractAllRows(scope=0x000000010705b600, sheetname=0x0000000000000000, hasHeaders=true, xreader=0x000070000384ad50, ioHeaders=size=0, transform=Function @ 0x000070000384ad30) at XlsxReaderFunctions.h:61 [opt]
        frame #10: 0x000000010a8a4782 xlsx.node`xlsx::extractAllData(scope=0x000000010705b600, filename=<unavailable>, hasHeaders=true, transform=Function @ 0x00007fd35c1dd370) at XlsxReaderFunctions.h:47 [opt]
        frame #11: 0x000000010a8a45db xlsx.node`xlsx::AsyncReader::Execute(this=0x000000010705b5a0) at AsyncReader.cpp:25 [opt]
        frame #12: 0x000000010a8a7c35 xlsx.node`Napi::AsyncWorker::OnExecute(env=<unavailable>, this_pointer=<unavailable>) at napi-inl.h:3170 [opt]
        frame #13: 0x00000001000937ff node`(anonymous namespace)::uvimpl::Work::ExecuteCallback(req=0x000000010705d7a0) at node_api.cc:3363
        frame #14: 0x000000010171c201 node`uv__queue_work(w=0x000000010705d7f8) at threadpool.c:259
        frame #15: 0x000000010171c8e6 node`worker(arg=0x0000000000000000) at threadpool.c:83
        frame #16: 0x0000000104d58665 libsystem_pthread.dylib`_pthread_body + 340
        frame #17: 0x0000000104d58511 libsystem_pthread.dylib`_pthread_start + 377
        frame #18: 0x0000000104d57bfd libsystem_pthread.dylib`thread_start + 13
      thread #11
        frame #0: 0x00007fff65f1aa1e libsystem_kernel.dylib`__psynch_cvwait + 10
        frame #1: 0x0000000104d595d9 libsystem_pthread.dylib`_pthread_cond_wait + 732
        frame #2: 0x00000001017374bd node`uv_cond_wait(cond=0x0000000102a7a6a0, mutex=0x0000000102a7a660) at thread.c:641
        frame #3: 0x000000010171c81f node`worker(arg=0x0000000000000000) at threadpool.c:63
        frame #4: 0x0000000104d58665 libsystem_pthread.dylib`_pthread_body + 340
        frame #5: 0x0000000104d58511 libsystem_pthread.dylib`_pthread_start + 377
        frame #6: 0x0000000104d57bfd libsystem_pthread.dylib`thread_start + 13
      thread #12
        frame #0: 0x00007fff65f1aa1e libsystem_kernel.dylib`__psynch_cvwait + 10
        frame #1: 0x0000000104d595d9 libsystem_pthread.dylib`_pthread_cond_wait + 732
        frame #2: 0x00000001017374bd node`uv_cond_wait(cond=0x0000000102a7a6a0, mutex=0x0000000102a7a660) at thread.c:641
        frame #3: 0x000000010171c81f node`worker(arg=0x0000000000000000) at threadpool.c:63
        frame #4: 0x0000000104d58665 libsystem_pthread.dylib`_pthread_body + 340
        frame #5: 0x0000000104d58511 libsystem_pthread.dylib`_pthread_start + 377
        frame #6: 0x0000000104d57bfd libsystem_pthread.dylib`thread_start + 13
      thread #13
        frame #0: 0x00007fff65f1aa1e libsystem_kernel.dylib`__psynch_cvwait + 10
        frame #1: 0x0000000104d595d9 libsystem_pthread.dylib`_pthread_cond_wait + 732
        frame #2: 0x00000001017374bd node`uv_cond_wait(cond=0x0000000102a7a6a0, mutex=0x0000000102a7a660) at thread.c:641
        frame #3: 0x000000010171c81f node`worker(arg=0x0000000000000000) at threadpool.c:63
        frame #4: 0x0000000104d58665 libsystem_pthread.dylib`_pthread_body + 340
        frame #5: 0x0000000104d58511 libsystem_pthread.dylib`_pthread_start + 377
        frame #6: 0x0000000104d57bfd libsystem_pthread.dylib`thread_start + 13
    
  4. webern commented on Jun 13, 2018

    @webern
    Author

    I am running plain native code and napi.h code from my Execute() function. I am not reaching into the N-API C api myself.

  5. mhdawson commented on Jun 13, 2018

    @mhdawson
    Member

    Ok, executing napi.h code from Execute() can cause JavaScript to execute which is not ok off the main thread. You need to limit what is in Execute() to plain native code and put anything that needs to interact with JavaScript in the OnOK() method.

  6. mhdawson commented on Jun 13, 2018

    @mhdawson
    Member

    This is a pull request with work-in-progress documentation: #272

  7. webern commented on Jun 13, 2018

    @webern
    Author

    OK, that's sounds like a good next attempt. It makes it hard to do my use case efficiently, but oh well.

  8. webern commented on Jun 13, 2018

    @webern
    Author

    One more important question before I re-write. Does OnOK block the JavaScript event loop? That would be bad for my use case because I need to marshal a significant amount of data from the native code into JavaScript objects. Thanks again.

  9. mhdawson commented on Jun 14, 2018

    @mhdawson
    Member

    Everything on the main thread will block the event loop, and OnOK runs on that loop.

    Are you moving an existing module over to N-API or is this a new module? I don't think this is any different from modules written with nan, but asking to be sure.

    Is it possible to get the results incrementally? ie have the native code do whatever processing is necessary and return a native structure. Then incrementally extract the data through multiple calls to the addon from JavaScript so that it does not block for the full time?

  10. changed the title [-]Exactly When does AsyncWorker destroy itself?[/-] [+]Segfault when using node-addon-api Objects during AsyncWorker::Execute[/+] on Jun 14, 2018
  11. webern commented on Jun 14, 2018

    @webern
    Author

    I am new to JavaScript as well as Node.js addons. This is my first attempt at a Node.js addon. I started using v8.h and node.h and can't remember how I chose to switch to napi.h. I haven't use NAN so haven't tried to compare anything to NAN.

    In general, if it is impossible to access the 'JavaScript' objects on a separate thread, then Node.js itself looks like a bad choice for my project since marshaling my data back-and-forth from native objects to JavaScript objects might negate the performance gains of doing operations in native code. Ultimately it feels like I should have chosen Go for this project.

    Anyway, in my use-case, blocking the main thread for 10 seconds or so isn't the end of the world, I'm just disappointed by Node.js limitations for my use case. I need to learn about worker farms or child processes next to see if that can help. What's not clear to me yet is whether or not I can pass a huge array of JavaScript objects to a child process or worker and receive those objects back.

    I will open a new thread for additional issues that I am having with AsyncWorker and close this issue as you have resolved the segfault problem I was having.

    Also note that I added a comment in the new AsyncWorker documentation pull request #272 asking for more detail about how the object is destroyed.

    Thanks.

  12. mhdawson commented on Jun 14, 2018

    @mhdawson
    Member

    @webern thanks for the comments and input.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions