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

View File

@ -31,6 +31,7 @@
#include "firebird.h" #include "firebird.h"
#include "../common/classes/alloc.h" #include "../common/classes/alloc.h"
#include "../common/classes/array.h" #include "../common/classes/array.h"
#include "../common/classes/condition.h"
#include "../common/classes/fb_string.h" #include "../common/classes/fb_string.h"
#include "../common/classes/GenericMap.h" #include "../common/classes/GenericMap.h"
#include "../common/classes/init.h" #include "../common/classes/init.h"
@ -43,10 +44,13 @@
namespace Jrd namespace Jrd
{ {
class WorkerAttachment;
class WorkerStableAttachment : public SysStableAttachment class WorkerStableAttachment : public SysStableAttachment
{ {
public: public:
static WorkerStableAttachment* create(FbStatusVector* status, Database* dbb, JProvider* provider); static WorkerStableAttachment* create(FbStatusVector* status, Database* dbb, JProvider* provider,
WorkerAttachment* workers);
void fini(); void fini();
@ -54,8 +58,10 @@ protected:
virtual void doOnIdleTimer(Firebird::TimerImpl* timer); virtual void doOnIdleTimer(Firebird::TimerImpl* timer);
private: private:
explicit WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* att); explicit WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* att, WorkerAttachment* workers);
virtual ~WorkerStableAttachment(); virtual ~WorkerStableAttachment();
WorkerAttachment* m_workers;
}; };
@ -77,6 +83,8 @@ private:
class WorkerAttachment class WorkerAttachment
{ {
friend class WorkerStableAttachment;
public: public:
explicit WorkerAttachment(); explicit WorkerAttachment();
@ -93,10 +101,14 @@ public:
private: private:
static WorkerAttachment* getByName(const Firebird::PathName& dbname); 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); static void doDetach(FbStatusVector* status, Jrd::StableAttachmentPart* sAtt);
void clear(bool checkRefs); void clear(bool checkRefs);
void incWorkers();
void decWorkers();
void waitForWorkers();
typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left<Firebird::PathName, WorkerAttachment*> > > typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left<Firebird::PathName, WorkerAttachment*> > >
MapDbIdToWorkAtts; MapDbIdToWorkAtts;
@ -109,7 +121,15 @@ private:
Firebird::HalfStaticArray<Jrd::StableAttachmentPart*, 8> m_idleAtts; Firebird::HalfStaticArray<Jrd::StableAttachmentPart*, 8> m_idleAtts;
Firebird::SortedArray<Jrd::StableAttachmentPart*, Firebird::SortedArray<Jrd::StableAttachmentPart*,
Firebird::InlineStorage<Jrd::StableAttachmentPart*, 8> > m_activeAtts; 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 } // namespace Jrd