8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 14:43:03 +01:00

Fixed bug #8390 : Deadlock might happens when database is shutting down with internal worker attachments exists.

This commit is contained in:
Vlad Khorsun 2025-01-17 11:24:12 +02:00
parent 3b2489c5e0
commit 6f17277a95
2 changed files with 69 additions and 16 deletions

View File

@ -49,8 +49,10 @@ const unsigned WORKER_IDLE_TIMEOUT = 60; // 1 minute
/// class WorkerStableAttachment
WorkerStableAttachment::WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* attachment) :
SysStableAttachment(attachment)
WorkerStableAttachment::WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* attachment,
WorkerAttachment* workers) :
SysStableAttachment(attachment),
m_workers(workers)
{
UserId user;
user.setUserName("<Worker>");
@ -69,6 +71,7 @@ WorkerStableAttachment::WorkerStableAttachment(FbStatusVector* status, Jrd::Atta
Monitoring::publishAttachment(tdbb);
initDone();
m_workers->incWorkers();
}
WorkerStableAttachment::~WorkerStableAttachment()
@ -76,7 +79,8 @@ WorkerStableAttachment::~WorkerStableAttachment()
fini();
}
WorkerStableAttachment* WorkerStableAttachment::create(FbStatusVector* status, Database* dbb, JProvider* provider)
WorkerStableAttachment* WorkerStableAttachment::create(FbStatusVector* status, Database* dbb,
JProvider* provider, WorkerAttachment* workers)
{
Attachment* attachment = NULL;
try
@ -85,7 +89,7 @@ WorkerStableAttachment* WorkerStableAttachment::create(FbStatusVector* status, D
attachment->att_filename = dbb->dbb_filename;
attachment->att_flags |= ATT_worker;
WorkerStableAttachment* sAtt = FB_NEW WorkerStableAttachment(status, attachment);
WorkerStableAttachment* sAtt = FB_NEW WorkerStableAttachment(status, attachment, workers);
return sAtt;
}
catch (const Exception& ex)
@ -129,6 +133,8 @@ void WorkerStableAttachment::fini()
}
destroy(attachment);
m_workers->decWorkers();
}
/// class WorkerAttachment
@ -139,8 +145,7 @@ bool WorkerAttachment::m_shutdown = false;
WorkerAttachment::WorkerAttachment() :
m_idleAtts(*getDefaultMemoryPool()),
m_activeAtts(*getDefaultMemoryPool()),
m_cntUserAtts(0)
m_activeAtts(*getDefaultMemoryPool())
{
}
@ -177,6 +182,30 @@ void WorkerAttachment::decUserAtts(const PathName& dbname)
}
}
void WorkerAttachment::incWorkers()
{
fb_assert(Config::getServerMode() == MODE_SUPER);
MutexLockGuard guard(m_mutex, FB_FUNCTION);
++m_cntWorkers;
}
void WorkerAttachment::decWorkers()
{
fb_assert(Config::getServerMode() == MODE_SUPER);
MutexLockGuard guard(m_mutex, FB_FUNCTION);
if (--m_cntWorkers == 0)
m_noWorkers.notifyAll();
}
void WorkerAttachment::waitForWorkers()
{
MutexLockGuard guard(m_mutex, FB_FUNCTION);
while (m_cntWorkers != 0)
m_noWorkers.wait(m_mutex);
}
WorkerAttachment* WorkerAttachment::getByName(const PathName& dbname)
{
if (m_shutdown)
@ -230,13 +259,17 @@ void WorkerAttachment::shutdownDbb(Database* dbb)
if (Config::getServerMode() != MODE_SUPER)
return;
WorkerAttachment* item = NULL;
{
MutexLockGuard guard(m_mapMutex, FB_FUNCTION);
WorkerAttachment* item = NULL;
if (!m_map->get(dbb->dbb_filename, item))
return;
}
item->clear(false);
item->waitForWorkers();
}
StableAttachmentPart* WorkerAttachment::getAttachment(FbStatusVector* status, Database* dbb)
@ -301,7 +334,7 @@ StableAttachmentPart* WorkerAttachment::getAttachment(FbStatusVector* status, Da
MutexUnlockGuard unlock(item->m_mutex, FB_FUNCTION);
status->init();
sAtt = doAttach(status, dbb);
sAtt = item->doAttach(status, dbb);
if (!sAtt)
{
// log error ?
@ -439,7 +472,7 @@ StableAttachmentPart* WorkerAttachment::doAttach(FbStatusVector* status, Databas
//jInstance->setDbCryptCallback(&status, tdbb->getAttachment()->att_crypt_callback);
if (Config::getServerMode() == MODE_SUPER)
sAtt = WorkerStableAttachment::create(status, dbb, jInstance);
sAtt = WorkerStableAttachment::create(status, dbb, jInstance, this);
else
{
ClumpletWriter dpb(ClumpletReader::Tagged, MAX_DPB_SIZE, isc_dpb_version1);

View File

@ -31,6 +31,7 @@
#include "firebird.h"
#include "../common/classes/alloc.h"
#include "../common/classes/array.h"
#include "../common/classes/condition.h"
#include "../common/classes/fb_string.h"
#include "../common/classes/GenericMap.h"
#include "../common/classes/init.h"
@ -43,10 +44,13 @@
namespace Jrd
{
class WorkerAttachment;
class WorkerStableAttachment : public SysStableAttachment
{
public:
static WorkerStableAttachment* create(FbStatusVector* status, Database* dbb, JProvider* provider);
static WorkerStableAttachment* create(FbStatusVector* status, Database* dbb, JProvider* provider,
WorkerAttachment* workers);
void fini();
@ -54,8 +58,10 @@ protected:
virtual void doOnIdleTimer(Firebird::TimerImpl* timer);
private:
explicit WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* att);
explicit WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* att, WorkerAttachment* workers);
virtual ~WorkerStableAttachment();
WorkerAttachment* m_workers;
};
@ -77,6 +83,8 @@ private:
class WorkerAttachment
{
friend class WorkerStableAttachment;
public:
explicit WorkerAttachment();
@ -93,10 +101,14 @@ public:
private:
static WorkerAttachment* getByName(const Firebird::PathName& dbname);
static Jrd::StableAttachmentPart* doAttach(FbStatusVector* status, Jrd::Database* dbb);
Jrd::StableAttachmentPart* doAttach(FbStatusVector* status, Jrd::Database* dbb);
static void doDetach(FbStatusVector* status, Jrd::StableAttachmentPart* sAtt);
void clear(bool checkRefs);
void incWorkers();
void decWorkers();
void waitForWorkers();
typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left<Firebird::PathName, WorkerAttachment*> > >
MapDbIdToWorkAtts;
@ -109,7 +121,15 @@ private:
Firebird::HalfStaticArray<Jrd::StableAttachmentPart*, 8> m_idleAtts;
Firebird::SortedArray<Jrd::StableAttachmentPart*,
Firebird::InlineStorage<Jrd::StableAttachmentPart*, 8> > m_activeAtts;
int m_cntUserAtts;
// count of regular user attachments, used with non-shared Database
int m_cntUserAtts = 0;
// count of internal worker attachments, used with shared Database
int m_cntWorkers = 0;
// used to wait for "no internal workers" condition
Firebird::Condition m_noWorkers;
};
} // namespace Jrd