@@ -500,8 +500,10 @@ namespace
500500 void handler ()
501501 { }
502502
503+ int release ();
503504 private:
504- ~ConfiguredPlugin ();
505+ ~ConfiguredPlugin () {}
506+ void destroy ();
505507
506508 RefPtr<PluginModule> module ;
507509 unsigned int regPlugin;
@@ -653,10 +655,15 @@ namespace
653655
654656 GlobalPtr<PluginsMap> plugins;
655657
656- ConfiguredPlugin::~ConfiguredPlugin ()
658+ void ConfiguredPlugin::destroy ()
657659 {
658- MutexLockGuard g ( plugins->mutex , FB_FUNCTION);
660+ // plugins->mutex must be entered by current thread
659661
662+ #ifdef DEV_BUILD
663+ if (!plugins->mutex .tryEnter (FB_FUNCTION))
664+ fb_assert (false );
665+ plugins->mutex .leave ();
666+ #endif
660667 if (!destroyingPluginsMap)
661668 {
662669 plugins->remove (MapKey (module ->getPlugin (regPlugin).type , plugName));
@@ -676,6 +683,33 @@ namespace
676683#endif
677684 }
678685
686+ int ConfiguredPlugin::release ()
687+ {
688+ int x = --refCounter;
689+
690+ #ifdef DEBUG_PLUGINS
691+ fprintf (stderr, " ConfiguredPlugin::release %s %d\n " , plugName.c_str (), x);
692+ #endif
693+
694+ if (x == 0 )
695+ {
696+ { // plugins->mutex scope
697+ MutexLockGuard g (plugins->mutex , FB_FUNCTION);
698+ if (refCounter != 0 )
699+ return 1 ;
700+
701+ destroy ();
702+ }
703+
704+ // Must run out of mutex scope to avoid deadlock with PluginManager::threadDetach()
705+ // called when module is unloaded by dtor
706+ delete this ;
707+ return 0 ;
708+ }
709+
710+ return 1 ;
711+ }
712+
679713 PluginModule* modules = NULL ;
680714
681715 PluginModule* current = NULL ;
0 commit comments