- 
          
 - 
                Notifications
    
You must be signed in to change notification settings  - Fork 487
 
Description
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.
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?
