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:
parent
3b2489c5e0
commit
6f17277a95
@ -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);
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user