Skip to content

Commit

Permalink
Merge pull request #16 from gewang/main
Browse files Browse the repository at this point in the history
address Fauck crash on exit
  • Loading branch information
shakfu committed May 10, 2024
2 parents caab39a + e9acfc3 commit ac48003
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 5 deletions.
11 changes: 11 additions & 0 deletions source/projects/chuck/core/chuck_dl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,16 @@ Chuck_DL_MainThreadHook * CK_DLL_CALL ck_create_main_thread_hook( Chuck_DL_Query
return new Chuck_DL_MainThreadHook( hook, quit, bindle, query->carrier() );
}

//-----------------------------------------------------------------------------
// name: ck_register_callback_on_shutdown() | 1.5.2.5 (ge) added
// desc: register a callback function to be called on host exit
// (both natural or SIGINT)
//-----------------------------------------------------------------------------
void CK_DLL_CALL ck_register_callback_on_shutdown( Chuck_DL_Query * query, f_callback_on_shutdown cb, void * bindle )
{
// register
query->vm()->register_callback_on_shutdown( cb, bindle );
}

//-----------------------------------------------------------------------------
// name: ck_register_shreds_watcher()
Expand Down Expand Up @@ -1351,6 +1361,7 @@ Chuck_DL_Query::Chuck_DL_Query( Chuck_Carrier * carrier, Chuck_DLL * dll )
create_main_thread_hook = ck_create_main_thread_hook;
register_shreds_watcher = ck_register_shreds_watcher; // 1.5.1.5 (ge & andrew)
unregister_shreds_watcher = ck_unregister_shreds_watcher; // 1.5.1.5 (ge & andrew)
register_callback_on_shutdown = ck_register_callback_on_shutdown; // 1.5.2.5 (ge)
m_carrier = carrier;
dll_ref = dll; // 1.5.1.3 (ge) added

Expand Down
14 changes: 13 additions & 1 deletion source/projects/chuck/core/chuck_dl.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
#define CK_DLL_VERSION_MAJOR (10)
// minor API version: revisions
// minor API version of chuck must >= API version of chugin
#define CK_DLL_VERSION_MINOR (1)
#define CK_DLL_VERSION_MINOR (2)
#define CK_DLL_VERSION_MAKE(maj,min) ((t_CKUINT)(((maj) << 16) | (min)))
#define CK_DLL_VERSION_GETMAJOR(v) (((v) >> 16) & 0xFFFF)
#define CK_DLL_VERSION_GETMINOR(v) ((v) & 0xFFFF)
Expand Down Expand Up @@ -340,6 +340,8 @@ typedef t_CKBOOL (CK_DLL_CALL * f_tock)( Chuck_Object * SELF, Chuck_UAna * UANA,
typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadhook)( void * bindle );
// "main thread" quit (stop running hook)
typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadquit)( void * bindle );
// callback function, called on host shutdown
typedef void (CK_DLL_CALL * f_callback_on_shutdown)( void * bindle );
// shreds watcher callback
typedef void (CK_DLL_CALL * f_shreds_watcher)( Chuck_VM_Shred * SHRED, t_CKINT CODE, t_CKINT PARAM, Chuck_VM * VM, void * BINDLE );
// type instantiation callback
Expand Down Expand Up @@ -414,6 +416,8 @@ typedef void (CK_DLL_CALL * f_add_ugen_funcf_auto_num_channels)( Chuck_DL_Query
typedef t_CKBOOL (CK_DLL_CALL * f_end_class)( Chuck_DL_Query * query );
// create main thread hook- used for executing a "hook" function in the main thread of a primary chuck instance
typedef Chuck_DL_MainThreadHook * (CK_DLL_CALL * f_create_main_thread_hook)( Chuck_DL_Query * query, f_mainthreadhook hook, f_mainthreadquit quit, void * bindle );
// register a callback to be called on host shutdown, e.g., for chugin cleanup
typedef void (CK_DLL_CALL * f_register_callback_on_shutdown)( Chuck_DL_Query * query, f_callback_on_shutdown cb, void * bindle );
// register a callback function to receive notification from the VM about shreds (add, remove, etc.)
typedef void (CK_DLL_CALL * f_register_shreds_watcher)( Chuck_DL_Query * query, f_shreds_watcher cb, t_CKUINT options, void * bindle );
// unregister a shreds notification callback
Expand Down Expand Up @@ -589,6 +593,14 @@ struct Chuck_DL_Query
// -------------
f_create_main_thread_hook create_main_thread_hook;

public:
// -------------
// register a function to be run on host shutdown; this can be used
// for chugin cleanup when the host (chuck, miniAudicle, etc.) exits
// including on SIGINT (ctrl-c termination) | added 1.5.2.5 (ge)
// -------------
f_register_callback_on_shutdown register_callback_on_shutdown;

public:
// -------------
// register callback to be invoked by chuck host at various
Expand Down
49 changes: 49 additions & 0 deletions source/projects/chuck/core/chuck_vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,9 @@ t_CKBOOL Chuck_VM::shutdown()
// set state
m_init = FALSE;

// notify registered callbacks we are shutting down | 1.5.2.5 (ge) added
notify_callbacks_on_shutdown();

// relockdown (added 1.3.6.0)
// REFACTOR-2017: TODO -- remove once made per-VM
Chuck_VM_Object::lock_all();
Expand Down Expand Up @@ -1431,6 +1434,52 @@ Chuck_VM_Shred * Chuck_VM::get_current_shred() const



//-----------------------------------------------------------------------------
// name: register_callback_on_shutdown()
// cesc: register a callback to be called on VM shutdown | 1.5.2.5 (ge) added
//-----------------------------------------------------------------------------
void Chuck_VM::register_callback_on_shutdown( f_callback_on_shutdown cb, void * bindle )
{
// check
if( !cb ) return;

// ensure no duplicates
list<Chuck_VM_Callback_On_Shutdown>::iterator it = std::find( m_callbacks_on_shutdown.begin(),
m_callbacks_on_shutdown.end(), cb );
// add if not already preset
if( it == m_callbacks_on_shutdown.end() )
{
// append
m_callbacks_on_shutdown.push_back( Chuck_VM_Callback_On_Shutdown(cb, bindle) );
}
}




//-----------------------------------------------------------------------------
// name: notify_callbacks_on_shutdown()
// desc: notify callbacks on VM shutdown | 1.5.2.5 (ge) added
//-----------------------------------------------------------------------------
void Chuck_VM::notify_callbacks_on_shutdown()
{
// the function to call eventually
f_callback_on_shutdown f = NULL;
// iterator
list<Chuck_VM_Callback_On_Shutdown>::iterator it;
// iterate
for( it = m_callbacks_on_shutdown.begin(); it != m_callbacks_on_shutdown.end(); it++ )
{
// the function
f = (*it).cb;
// call it with user data
f( (*it).userdata );
}
}




//-----------------------------------------------------------------------------
// name: notify_watchers()
// desc: notify watchers for a particular subscription | 1.5.1.5
Expand Down
39 changes: 39 additions & 0 deletions source/projects/chuck/core/chuck_vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,33 @@ struct Chuck_VM_Status : public Chuck_Object



//-----------------------------------------------------------------------------
// name: struct Chuck_VM_Callback_On_Shutdown
// desc: an entry for a callback to be called on VM shutdown
//-----------------------------------------------------------------------------
struct Chuck_VM_Callback_On_Shutdown
{
// function pointer to call
f_callback_on_shutdown cb;
// user data
void * userdata;

// constructor
Chuck_VM_Callback_On_Shutdown( f_callback_on_shutdown f = NULL, void * data = NULL )
: cb(f), userdata(data) { }

// copy constructor
Chuck_VM_Callback_On_Shutdown( const Chuck_VM_Callback_On_Shutdown & other )
: cb(other.cb), userdata(other.userdata) { }

// ==
bool operator ==( const Chuck_VM_Callback_On_Shutdown & other )
{ return this->cb == other.cb; }
};




//-----------------------------------------------------------------------------
// name: struct Chuck_VM_Shreduler
// desc: a ChucK shreduler shredules shreds
Expand Down Expand Up @@ -657,6 +684,14 @@ struct Chuck_VM : public Chuck_Object
// remove shreds watcher callback | 1.5.1.5
void remove_watcher( f_shreds_watcher cb );

public:
// register a callback to be called on VM shutdown | 1.5.2.5 (ge) added
void register_callback_on_shutdown( f_callback_on_shutdown cb, void * bindle );

protected:
// notify callbacks on VM shutdown | 1.5.2.5 (ge) added
void notify_callbacks_on_shutdown();

//-----------------------------------------------------------------------------
// data
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -733,6 +768,10 @@ struct Chuck_VM : public Chuck_Object
std::list<Chuck_VM_Shreds_Watcher> m_shreds_watchers_remove;
std::list<Chuck_VM_Shreds_Watcher> m_shreds_watchers_suspend;
std::list<Chuck_VM_Shreds_Watcher> m_shreds_watchers_activate;

protected:
// 1.5.2.5 (ge) on major VM events callbacks
std::list<Chuck_VM_Callback_On_Shutdown> m_callbacks_on_shutdown;
};


Expand Down
88 changes: 86 additions & 2 deletions source/projects/chugins/Fauck/Faust.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ std::string getPathToFaustLibraries() {
#ifdef NOBUNDLE
const char* myDLLPath = getMyDLLPath();
std::filesystem::path p = std::filesystem::path(myDLLPath).parent_path().parent_path() / "faust" ;
std::cout << "path: " << p << std::endl;
std::cout << "faust library path: " << p << std::endl;
return p.string();
#else
// look for faustlibraries inside the bundle
Expand Down Expand Up @@ -851,14 +851,89 @@ class Faust
};


//-----------------------------------------------------------------------------
// name: class Faucktory | v0.2.0 added (ge)
// desc: a fauck factory for globally keep track of open Faust instances
// used as a date structure of "smart pointers" to ensure each is
// closed properly; currently, for example, an abrupt closing in
// ChucK (e.g., ctrl-c) or application closing (miniAudicle, Max, etc.)
// does not cleanup live objects, leading to crashes-on-exit like:
// ```
// libc++abi: terminating due to uncaught exception of type
// std::__1::system_error: recursive_mutex lock failed: Invalid argument
// zsh: abort
// ```
//-----------------------------------------------------------------------------
class Faucktory
{
public:
// destructor | to be called on exit
~Faucktory() { cleanup(); }

// add a Faust object to track
void add( Faust * fck )
{
// insert
faucks[fck] = fck;
}
// remove a Faust object
void remove( Faust * fck )
{
// count
if( faucks.count(fck) == 0 ) return;
// remove from map
faucks.erase( fck );
}
// cleanup all tracked Faust objects
void cleanup()
{
std::map<Faust *, Faust *>::iterator it;
for( it = faucks.begin(); it != faucks.end(); it++ )
{
// get the pointer
Faust * fck = it->second;
// clean it up
if( fck ) fck->clear();
}
// clear the map entries
faucks.clear();
}

public: // singleton API
static Faucktory * instance()
{
// instance
if( !o_faucktory ) { o_faucktory = new Faucktory(); }
return o_faucktory;
}

protected:
std::map<Faust *, Faust *> faucks;

private: // enforce singleton
Faucktory() { }
static Faucktory * o_faucktory;
};

// static global faucktory | v0.2.0 (ge) added
Faucktory * Faucktory::o_faucktory = NULL;

// callback to be called on host shutdown (so we can clean up)
static void cb_on_host_shutdown( void * bindle )
{
// explcitly call cleanup (in case of SIGINT, global object dtors doesn't run)
Faucktory::instance()->cleanup();
}


//-----------------------------------------------------------------------------
// info function: ChucK calls this when loading/probing the chugin
// NOTE: please customize these info fields below; they will be used for
// chugins loading, probing, and package management and documentation
//-----------------------------------------------------------------------------
CK_DLL_INFO( Faust )
{
QUERY->setinfo( QUERY, CHUGIN_INFO_CHUGIN_VERSION, "v0.0.1" );
QUERY->setinfo( QUERY, CHUGIN_INFO_CHUGIN_VERSION, "v0.2.0" );
QUERY->setinfo( QUERY, CHUGIN_INFO_AUTHORS, "Ge Wang, Romain Michon, David Braun" );
QUERY->setinfo( QUERY, CHUGIN_INFO_DESCRIPTION, "A chugin which dynamically compiles and executes FAUST code via LLVM." );
QUERY->setinfo( QUERY, CHUGIN_INFO_URL, "https://github.com/ccrma/fauck" );
Expand All @@ -876,6 +951,9 @@ CK_DLL_QUERY( Faust )
// hmm, don't change this...
QUERY->setname(QUERY, "Faust");

// register a callback to be called upon host shutdown (so we can clean up)
QUERY->register_callback_on_shutdown(QUERY, cb_on_host_shutdown, NULL);

// begin the class definition
// can change the second argument to extend a different ChucK class
QUERY->begin_class(QUERY, "Faust", "UGen");
Expand Down Expand Up @@ -1006,6 +1084,9 @@ CK_DLL_CTOR(faust_ctor)

// store the pointer in the ChucK object member
OBJ_MEMBER_INT(SELF, faust_data_offset) = (t_CKINT) faust_obj;

// add to global registry
Faucktory::instance()->add( faust_obj );
}

// implementation for the destructor
Expand All @@ -1014,6 +1095,9 @@ CK_DLL_DTOR(faust_dtor)
// get our c++ class pointer
Faust * faust_obj = (Faust *) OBJ_MEMBER_INT(SELF, faust_data_offset);

// remove from global registry
Faucktory::instance()->remove( faust_obj );

// clean up (this macro tests for NULL, deletes, and zeros out the variable)
CK_SAFE_DELETE( faust_obj );
// set the data field to 0
Expand Down
16 changes: 14 additions & 2 deletions source/projects/chugins/chuck/include/chugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
// 1.5.0.0 (ge) | moved to chuck.h for at-a-glance visibility
// 1.5.2.0 (ge) | moved to chuck_def.h for chugins headers streamlining
//-----------------------------------------------------------------------------
#define CHUCK_VERSION_STRING "1.5.2.4 (chai)"
#define CHUCK_VERSION_STRING "1.5.2.5-dev (chai)"
//-----------------------------------------------------------------------------


Expand Down Expand Up @@ -1158,7 +1158,7 @@ struct a_Program_ { a_Section section; a_Program next; uint32_t line; uint32_t w
#define CK_DLL_VERSION_MAJOR (10)
// minor API version: revisions
// minor API version of chuck must >= API version of chugin
#define CK_DLL_VERSION_MINOR (1)
#define CK_DLL_VERSION_MINOR (2)
#define CK_DLL_VERSION_MAKE(maj,min) ((t_CKUINT)(((maj) << 16) | (min)))
#define CK_DLL_VERSION_GETMAJOR(v) (((v) >> 16) & 0xFFFF)
#define CK_DLL_VERSION_GETMINOR(v) ((v) & 0xFFFF)
Expand Down Expand Up @@ -1435,6 +1435,8 @@ typedef t_CKBOOL (CK_DLL_CALL * f_tock)( Chuck_Object * SELF, Chuck_UAna * UANA,
typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadhook)( void * bindle );
// "main thread" quit (stop running hook)
typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadquit)( void * bindle );
// callback function, called on host shutdown
typedef void (CK_DLL_CALL * f_callback_on_shutdown)( void * bindle );
// shreds watcher callback
typedef void (CK_DLL_CALL * f_shreds_watcher)( Chuck_VM_Shred * SHRED, t_CKINT CODE, t_CKINT PARAM, Chuck_VM * VM, void * BINDLE );
// type instantiation callback
Expand Down Expand Up @@ -1509,6 +1511,8 @@ typedef void (CK_DLL_CALL * f_add_ugen_funcf_auto_num_channels)( Chuck_DL_Query
typedef t_CKBOOL (CK_DLL_CALL * f_end_class)( Chuck_DL_Query * query );
// create main thread hook- used for executing a "hook" function in the main thread of a primary chuck instance
typedef Chuck_DL_MainThreadHook * (CK_DLL_CALL * f_create_main_thread_hook)( Chuck_DL_Query * query, f_mainthreadhook hook, f_mainthreadquit quit, void * bindle );
// register a callback to be called on host shutdown, e.g., for chugin cleanup
typedef void (CK_DLL_CALL * f_register_callback_on_shutdown)( Chuck_DL_Query * query, f_callback_on_shutdown cb, void * bindle );
// register a callback function to receive notification from the VM about shreds (add, remove, etc.)
typedef void (CK_DLL_CALL * f_register_shreds_watcher)( Chuck_DL_Query * query, f_shreds_watcher cb, t_CKUINT options, void * bindle );
// unregister a shreds notification callback
Expand Down Expand Up @@ -1684,6 +1688,14 @@ struct Chuck_DL_Query
// -------------
f_create_main_thread_hook create_main_thread_hook;

public:
// -------------
// register a function to be run on host shutdown; this can be used
// for chugin cleanup on the host (chuck, miniAudicle, etc.) exits
// added 1.5.2.5 (ge)
// -------------
f_register_callback_on_shutdown register_callback_on_shutdown;

public:
// -------------
// register callback to be invoked by chuck host at various
Expand Down

0 comments on commit ac48003

Please sign in to comment.