Skip to content

Commit 0a36985

Browse files
committed
Fixed #8449: Races when server is closed during forced database shutdown
(cherry picked from commit df1e8aa)
1 parent 3fb0bbf commit 0a36985

File tree

6 files changed

+60
-3
lines changed

6 files changed

+60
-3
lines changed

src/common/classes/init.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ class GlobalPtr : private InstanceControl
159159
{
160160
return instance;
161161
}
162+
163+
operator bool() noexcept
164+
{
165+
return instance;
166+
}
162167
};
163168

164169
// InitMutex - executes static void C::init() once and only once

src/yvalve/MasterImplementation.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,11 @@ Mutex& pauseTimer()
404404
return timerPause;
405405
}
406406

407+
bool timerThreadStopped()
408+
{
409+
return stopTimerThread.value() != 0;
410+
}
411+
407412
} // namespace Why
408413

409414

src/yvalve/MasterImplementation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ namespace Why
7272
void shutdownTimers();
7373

7474
Firebird::Mutex& pauseTimer();
75+
76+
bool timerThreadStopped();
7577
} // namespace Why
7678

7779
#endif // YVALVE_MASTER_IMPLEMENTATION_H

src/yvalve/PluginManager.cpp

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "../common/classes/fb_string.h"
3737
#include "../common/classes/init.h"
3838
#include "../common/classes/semaphore.h"
39+
#include "../common/classes/RefMutex.h"
3940
#include "../common/config/config.h"
4041
#include "../common/config/config_file.h"
4142
#include "../common/utils_proto.h"
@@ -455,7 +456,7 @@ namespace
455456
const PathName& pplugName)
456457
: module(pmodule), regPlugin(preg), pluginLoaderConfig(pconfig),
457458
confName(getPool(), pconfName), plugName(getPool(), pplugName),
458-
delay(DEFAULT_DELAY)
459+
processingDelayedDelete(false), delay(DEFAULT_DELAY)
459460
{
460461
if (pluginLoaderConfig.hasData())
461462
{
@@ -472,7 +473,7 @@ namespace
472473
#ifdef DEBUG_PLUGINS
473474
RegisteredPlugin& r(module->getPlugin(regPlugin));
474475
fprintf(stderr, " ConfiguredPlugin %s module %s registered as %s type %d order %d\n",
475-
plugName.c_str(), module->getName(), r.name, r.type, regPlugin);
476+
plugName.c_str(), module->getName(), r.name.c_str(), r.type, regPlugin);
476477
#endif
477478
}
478479

@@ -516,6 +517,8 @@ namespace
516517
{ }
517518

518519
int release();
520+
static void processDelayedDelete();
521+
519522
private:
520523
~ConfiguredPlugin() {}
521524
void destroy();
@@ -525,6 +528,7 @@ namespace
525528
RefPtr<ConfigFile> pluginLoaderConfig;
526529
PathName confName;
527530
PathName plugName;
531+
bool processingDelayedDelete;
528532

529533
static const FB_UINT64 DEFAULT_DELAY = 1000000 * 60; // 1 min
530534
FB_UINT64 delay;
@@ -587,7 +591,7 @@ namespace
587591
~FactoryParameter()
588592
{
589593
#ifdef DEBUG_PLUGINS
590-
fprintf(stderr, "~FactoryParameter places configuredPlugin %s in unload query for %d seconds\n",
594+
fprintf(stderr, "~FactoryParameter places configuredPlugin %s in unload query for %lld seconds\n",
591595
configuredPlugin->getPlugName(), configuredPlugin->getReleaseDelay() / 1000000);
592596
#endif
593597
FbLocalStatus ls;
@@ -696,6 +700,9 @@ namespace
696700
#endif
697701
}
698702

703+
typedef HalfStaticArray<ConfiguredPlugin*, 16> DelayedDelete;
704+
static GlobalPtr<DelayedDelete> delayedDelete;
705+
699706
int ConfiguredPlugin::release()
700707
{
701708
int x = --refCounter;
@@ -711,6 +718,15 @@ namespace
711718
if (refCounter != 0)
712719
return 1;
713720

721+
if (Why::timerThreadStopped() && !processingDelayedDelete && delayedDelete)
722+
{
723+
// delay delete
724+
addRef();
725+
delayedDelete->push(this);
726+
727+
return 1;
728+
}
729+
714730
destroy();
715731
}
716732

@@ -723,6 +739,26 @@ namespace
723739
return 1;
724740
}
725741

742+
void ConfiguredPlugin::processDelayedDelete()
743+
{
744+
DelayedDelete& dd(delayedDelete);
745+
MutexEnsureUnlock g(plugins->mutex, FB_FUNCTION);
746+
g.enter();
747+
for (unsigned n = 0; n < dd.getCount(); ++n)
748+
{
749+
ConfiguredPlugin* ptr = dd[n];
750+
if (ptr)
751+
{
752+
g.leave();
753+
ptr->processingDelayedDelete = true;
754+
ptr->release();
755+
g.enter();
756+
}
757+
dd[n] = nullptr;
758+
}
759+
delayedDelete->clear();
760+
}
761+
726762
PluginModule* modules = NULL;
727763

728764
PluginModule* current = NULL;
@@ -1213,6 +1249,10 @@ void PluginManager::threadDetach()
12131249
modules->threadDetach();
12141250
}
12151251

1252+
void PluginManager::deleteDelayed()
1253+
{
1254+
ConfiguredPlugin::processDelayedDelete();
1255+
}
12161256

12171257
} // namespace Firebird
12181258

src/yvalve/PluginManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class PluginManager : public AutoIface<IPluginManagerImpl<PluginManager, CheckSt
5555
static void shutdown();
5656
static void waitForType(unsigned int typeThatMustGoAway);
5757
static void threadDetach();
58+
static void deleteDelayed();
5859
};
5960

6061
} // namespace Firebird

src/yvalve/why.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6690,7 +6690,10 @@ void Dispatcher::shutdown(CheckStatusWrapper* userStatus, unsigned int timeout,
66906690
}
66916691

66926692
if (hasThreads)
6693+
{
6694+
PluginManager::deleteDelayed();
66936695
continue;
6696+
}
66946697

66956698
Stack<YAttachment*, 64> attStack;
66966699
{
@@ -6720,6 +6723,7 @@ void Dispatcher::shutdown(CheckStatusWrapper* userStatus, unsigned int timeout,
67206723
attachment->release();
67216724
}
67226725

6726+
PluginManager::deleteDelayed();
67236727
}
67246728

67256729
// ... and wait for all providers to go away

0 commit comments

Comments
 (0)