Skip to content

Commit df1e8aa

Browse files
committed
Fixed #8449: Races when server is closed during forced database shutdown
1 parent 58633c8 commit df1e8aa

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"
@@ -453,7 +454,7 @@ namespace
453454
const PathName& pplugName)
454455
: module(pmodule), regPlugin(preg), pluginLoaderConfig(pconfig),
455456
confName(getPool(), pconfName), plugName(getPool(), pplugName),
456-
delay(DEFAULT_DELAY)
457+
processingDelayedDelete(false), delay(DEFAULT_DELAY)
457458
{
458459
if (pluginLoaderConfig.hasData())
459460
{
@@ -470,7 +471,7 @@ namespace
470471
#ifdef DEBUG_PLUGINS
471472
RegisteredPlugin& r(module->getPlugin(regPlugin));
472473
fprintf(stderr, " ConfiguredPlugin %s module %s registered as %s type %d order %d\n",
473-
plugName.c_str(), module->getName(), r.name, r.type, regPlugin);
474+
plugName.c_str(), module->getName(), r.name.c_str(), r.type, regPlugin);
474475
#endif
475476
}
476477

@@ -514,6 +515,8 @@ namespace
514515
{ }
515516

516517
int release();
518+
static void processDelayedDelete();
519+
517520
private:
518521
~ConfiguredPlugin() {}
519522
void destroy();
@@ -523,6 +526,7 @@ namespace
523526
RefPtr<ConfigFile> pluginLoaderConfig;
524527
PathName confName;
525528
PathName plugName;
529+
bool processingDelayedDelete;
526530

527531
static const FB_UINT64 DEFAULT_DELAY = 1000000 * 60; // 1 min
528532
FB_UINT64 delay;
@@ -585,7 +589,7 @@ namespace
585589
~FactoryParameter()
586590
{
587591
#ifdef DEBUG_PLUGINS
588-
fprintf(stderr, "~FactoryParameter places configuredPlugin %s in unload query for %d seconds\n",
592+
fprintf(stderr, "~FactoryParameter places configuredPlugin %s in unload query for %lld seconds\n",
589593
configuredPlugin->getPlugName(), configuredPlugin->getReleaseDelay() / 1000000);
590594
#endif
591595
FbLocalStatus ls;
@@ -694,6 +698,9 @@ namespace
694698
#endif
695699
}
696700

701+
typedef HalfStaticArray<ConfiguredPlugin*, 16> DelayedDelete;
702+
static GlobalPtr<DelayedDelete> delayedDelete;
703+
697704
int ConfiguredPlugin::release()
698705
{
699706
int x = --refCounter;
@@ -709,6 +716,15 @@ namespace
709716
if (refCounter != 0)
710717
return 1;
711718

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

@@ -721,6 +737,26 @@ namespace
721737
return 1;
722738
}
723739

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

726762
PluginModule* current = NULL;
@@ -1211,6 +1247,10 @@ void PluginManager::threadDetach()
12111247
modules->threadDetach();
12121248
}
12131249

1250+
void PluginManager::deleteDelayed()
1251+
{
1252+
ConfiguredPlugin::processDelayedDelete();
1253+
}
12141254

12151255
} // namespace Firebird
12161256

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
@@ -6880,7 +6880,10 @@ void Dispatcher::shutdown(CheckStatusWrapper* userStatus, unsigned int timeout,
68806880
}
68816881

68826882
if (hasThreads)
6883+
{
6884+
PluginManager::deleteDelayed();
68836885
continue;
6886+
}
68846887

68856888
Stack<YAttachment*, 64> attStack;
68866889
{
@@ -6910,6 +6913,7 @@ void Dispatcher::shutdown(CheckStatusWrapper* userStatus, unsigned int timeout,
69106913
attachment->release();
69116914
}
69126915

6916+
PluginManager::deleteDelayed();
69136917
}
69146918

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

0 commit comments

Comments
 (0)