Skip to content

Commit e9894bf

Browse files
committed
fix(core): also register global shutdown hook in PackageManager(Impl&) constructor
Manager::Manager() bypasses PackageManager() default constructor and calls PackageManager(Impl&) directly. The default constructor registered a global shutdown hook (setGlobalShutdownHook) to release ObjectPool references before plugin DLLs are unloaded, but the Impl& constructor path was missing this registration. Without this hook, if the Runtime destruction callback (registered by setupG2pOnnxDriver) does not fire (e.g. multiple Runtime instances, Runtime not destroyed before static Manager destruction), the Manager singleton's destructor at process exit triggers cleanup of Task objects whose vtables reside in already-unloaded plugin DLLs, causing a use-after-free crash in shared_ptr::_Decref. This completes the fix chain: - 3d1d66e (weak_ptr in factory) - 5772823 (destruction callback) - b4e2806 (global hook in default constructor) - This commit (global hook in Impl& constructor)
1 parent 674154f commit e9894bf

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

‎lib/G2P/Core/PackageManager.cpp‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,28 @@ namespace srt::g2p {
617617
// ============================================================================
618618

619619
PackageManager::PackageManager(Impl &impl) : _impl(&impl) {
620+
// Register a process-wide shutdown hook so that when ANY Runtime
621+
// instance destructs (before plugin DLLs are unloaded), this
622+
// PackageManager's ObjectPool references are released while the
623+
// plugin DLLs are still loaded.
624+
//
625+
// This is necessary because Manager (a subclass that uses this
626+
// constructor path) is a static singleton whose destructor runs
627+
// AFTER the host's Runtime. Without this hook, the Manager
628+
// destructor would release Task/SessionFactory shared_ptrs whose
629+
// vtables reside in already-unloaded plugin DLLs, causing
630+
// use-after-free crashes in shared_ptr::_Decref.
631+
//
632+
// The hook captures `this` (raw pointer to the static singleton,
633+
// whose address is stable for the process lifetime). shutdown() is
634+
// idempotent, so a later destructor call is a no-op.
635+
//
636+
// NOTE: This is identical to the hook registration in the default
637+
// constructor; both paths must register it since Manager bypasses
638+
// the default constructor.
639+
srt::core::Runtime::setGlobalShutdownHook([this]() {
640+
_impl->shutdown();
641+
});
620642
}
621643

622644
PackageManager::PackageManager() : srt::core::PluginFactory(), _impl(new Impl(this)) {

0 commit comments

Comments
 (0)