Skip to content

Commit

Permalink
Fixed #8449: Races when server is closed during forced database shutdown
Browse files Browse the repository at this point in the history
(cherry picked from commit df1e8aa)
  • Loading branch information
AlexPeshkoff committed Feb 25, 2025
1 parent 00b699c commit 2e14d97
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 3 deletions.
5 changes: 5 additions & 0 deletions src/common/classes/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ class GlobalPtr : private InstanceControl
{
return instance;
}

operator bool() noexcept
{
return instance;
}
};

// InitMutex - executes static void C::init() once and only once
Expand Down
5 changes: 5 additions & 0 deletions src/yvalve/MasterImplementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,11 @@ Mutex& pauseTimer()
return timerPause;
}

bool timerThreadStopped()
{
return stopTimerThread.value() != 0;
}

} // namespace Why


Expand Down
2 changes: 2 additions & 0 deletions src/yvalve/MasterImplementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ namespace Why
void shutdownTimers();

Firebird::Mutex& pauseTimer();

bool timerThreadStopped();
} // namespace Why

#endif // YVALVE_MASTER_IMPLEMENTATION_H
46 changes: 43 additions & 3 deletions src/yvalve/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "../common/classes/fb_string.h"
#include "../common/classes/init.h"
#include "../common/classes/semaphore.h"
#include "../common/classes/RefMutex.h"
#include "../common/config/config.h"
#include "../common/config/config_file.h"
#include "../common/utils_proto.h"
Expand Down Expand Up @@ -453,7 +454,7 @@ namespace
const PathName& pplugName)
: module(pmodule), regPlugin(preg), pluginLoaderConfig(pconfig),
confName(getPool(), pconfName), plugName(getPool(), pplugName),
delay(DEFAULT_DELAY)
processingDelayedDelete(false), delay(DEFAULT_DELAY)
{
if (pluginLoaderConfig.hasData())
{
Expand All @@ -470,7 +471,7 @@ namespace
#ifdef DEBUG_PLUGINS
RegisteredPlugin& r(module->getPlugin(regPlugin));
fprintf(stderr, " ConfiguredPlugin %s module %s registered as %s type %d order %d\n",
plugName.c_str(), module->getName(), r.name, r.type, regPlugin);
plugName.c_str(), module->getName(), r.name.c_str(), r.type, regPlugin);
#endif
}

Expand Down Expand Up @@ -514,6 +515,8 @@ namespace
{ }

int release();
static void processDelayedDelete();

private:
~ConfiguredPlugin() {}
void destroy();
Expand All @@ -523,6 +526,7 @@ namespace
RefPtr<ConfigFile> pluginLoaderConfig;
PathName confName;
PathName plugName;
bool processingDelayedDelete;

static const FB_UINT64 DEFAULT_DELAY = 1000000 * 60; // 1 min
FB_UINT64 delay;
Expand Down Expand Up @@ -585,7 +589,7 @@ namespace
~FactoryParameter()
{
#ifdef DEBUG_PLUGINS
fprintf(stderr, "~FactoryParameter places configuredPlugin %s in unload query for %d seconds\n",
fprintf(stderr, "~FactoryParameter places configuredPlugin %s in unload query for %lld seconds\n",
configuredPlugin->getPlugName(), configuredPlugin->getReleaseDelay() / 1000000);
#endif
FbLocalStatus ls;
Expand Down Expand Up @@ -694,6 +698,9 @@ namespace
#endif
}

typedef HalfStaticArray<ConfiguredPlugin*, 16> DelayedDelete;
static GlobalPtr<DelayedDelete> delayedDelete;

int ConfiguredPlugin::release()
{
int x = --refCounter;
Expand All @@ -709,6 +716,15 @@ namespace
if (refCounter != 0)
return 1;

if (Why::timerThreadStopped() && !processingDelayedDelete && delayedDelete)
{
// delay delete
addRef();
delayedDelete->push(this);

return 1;
}

destroy();
}

Expand All @@ -721,6 +737,26 @@ namespace
return 1;
}

void ConfiguredPlugin::processDelayedDelete()
{
DelayedDelete& dd(delayedDelete);
MutexEnsureUnlock g(plugins->mutex, FB_FUNCTION);
g.enter();
for (unsigned n = 0; n < dd.getCount(); ++n)
{
ConfiguredPlugin* ptr = dd[n];
if (ptr)
{
g.leave();
ptr->processingDelayedDelete = true;
ptr->release();
g.enter();
}
dd[n] = nullptr;
}
delayedDelete->clear();
}

PluginModule* modules = NULL;

PluginModule* current = NULL;
Expand Down Expand Up @@ -1211,6 +1247,10 @@ void PluginManager::threadDetach()
modules->threadDetach();
}

void PluginManager::deleteDelayed()
{
ConfiguredPlugin::processDelayedDelete();
}

} // namespace Firebird

Expand Down
1 change: 1 addition & 0 deletions src/yvalve/PluginManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class PluginManager : public AutoIface<IPluginManagerImpl<PluginManager, CheckSt
static void shutdown();
static void waitForType(unsigned int typeThatMustGoAway);
static void threadDetach();
static void deleteDelayed();
};

} // namespace Firebird
Expand Down
4 changes: 4 additions & 0 deletions src/yvalve/why.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6880,7 +6880,10 @@ void Dispatcher::shutdown(CheckStatusWrapper* userStatus, unsigned int timeout,
}

if (hasThreads)
{
PluginManager::deleteDelayed();
continue;
}

Stack<YAttachment*, 64> attStack;
{
Expand Down Expand Up @@ -6910,6 +6913,7 @@ void Dispatcher::shutdown(CheckStatusWrapper* userStatus, unsigned int timeout,
attachment->release();
}

PluginManager::deleteDelayed();
}

// ... and wait for all providers to go away
Expand Down

0 comments on commit 2e14d97

Please sign in to comment.