Skip to content

Commit 6f17277

Browse files
committed
Fixed bug #8390 : Deadlock might happens when database is shutting down with internal worker attachments exists.
1 parent 3b2489c commit 6f17277

File tree

2 files changed

+69
-16
lines changed

2 files changed

+69
-16
lines changed

src/jrd/WorkerAttachment.cpp

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,10 @@ const unsigned WORKER_IDLE_TIMEOUT = 60; // 1 minute
4949

5050
/// class WorkerStableAttachment
5151

52-
WorkerStableAttachment::WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* attachment) :
53-
SysStableAttachment(attachment)
52+
WorkerStableAttachment::WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* attachment,
53+
WorkerAttachment* workers) :
54+
SysStableAttachment(attachment),
55+
m_workers(workers)
5456
{
5557
UserId user;
5658
user.setUserName("<Worker>");
@@ -69,14 +71,16 @@ WorkerStableAttachment::WorkerStableAttachment(FbStatusVector* status, Jrd::Atta
6971
Monitoring::publishAttachment(tdbb);
7072

7173
initDone();
74+
m_workers->incWorkers();
7275
}
7376

7477
WorkerStableAttachment::~WorkerStableAttachment()
7578
{
7679
fini();
7780
}
7881

79-
WorkerStableAttachment* WorkerStableAttachment::create(FbStatusVector* status, Database* dbb, JProvider* provider)
82+
WorkerStableAttachment* WorkerStableAttachment::create(FbStatusVector* status, Database* dbb,
83+
JProvider* provider, WorkerAttachment* workers)
8084
{
8185
Attachment* attachment = NULL;
8286
try
@@ -85,7 +89,7 @@ WorkerStableAttachment* WorkerStableAttachment::create(FbStatusVector* status, D
8589
attachment->att_filename = dbb->dbb_filename;
8690
attachment->att_flags |= ATT_worker;
8791

88-
WorkerStableAttachment* sAtt = FB_NEW WorkerStableAttachment(status, attachment);
92+
WorkerStableAttachment* sAtt = FB_NEW WorkerStableAttachment(status, attachment, workers);
8993
return sAtt;
9094
}
9195
catch (const Exception& ex)
@@ -129,6 +133,8 @@ void WorkerStableAttachment::fini()
129133
}
130134

131135
destroy(attachment);
136+
137+
m_workers->decWorkers();
132138
}
133139

134140
/// class WorkerAttachment
@@ -139,8 +145,7 @@ bool WorkerAttachment::m_shutdown = false;
139145

140146
WorkerAttachment::WorkerAttachment() :
141147
m_idleAtts(*getDefaultMemoryPool()),
142-
m_activeAtts(*getDefaultMemoryPool()),
143-
m_cntUserAtts(0)
148+
m_activeAtts(*getDefaultMemoryPool())
144149
{
145150
}
146151

@@ -177,6 +182,30 @@ void WorkerAttachment::decUserAtts(const PathName& dbname)
177182
}
178183
}
179184

185+
void WorkerAttachment::incWorkers()
186+
{
187+
fb_assert(Config::getServerMode() == MODE_SUPER);
188+
189+
MutexLockGuard guard(m_mutex, FB_FUNCTION);
190+
++m_cntWorkers;
191+
}
192+
193+
void WorkerAttachment::decWorkers()
194+
{
195+
fb_assert(Config::getServerMode() == MODE_SUPER);
196+
197+
MutexLockGuard guard(m_mutex, FB_FUNCTION);
198+
if (--m_cntWorkers == 0)
199+
m_noWorkers.notifyAll();
200+
}
201+
202+
void WorkerAttachment::waitForWorkers()
203+
{
204+
MutexLockGuard guard(m_mutex, FB_FUNCTION);
205+
while (m_cntWorkers != 0)
206+
m_noWorkers.wait(m_mutex);
207+
}
208+
180209
WorkerAttachment* WorkerAttachment::getByName(const PathName& dbname)
181210
{
182211
if (m_shutdown)
@@ -230,13 +259,17 @@ void WorkerAttachment::shutdownDbb(Database* dbb)
230259
if (Config::getServerMode() != MODE_SUPER)
231260
return;
232261

233-
MutexLockGuard guard(m_mapMutex, FB_FUNCTION);
234-
235262
WorkerAttachment* item = NULL;
236-
if (!m_map->get(dbb->dbb_filename, item))
237-
return;
263+
264+
{
265+
MutexLockGuard guard(m_mapMutex, FB_FUNCTION);
266+
267+
if (!m_map->get(dbb->dbb_filename, item))
268+
return;
269+
}
238270

239271
item->clear(false);
272+
item->waitForWorkers();
240273
}
241274

242275
StableAttachmentPart* WorkerAttachment::getAttachment(FbStatusVector* status, Database* dbb)
@@ -301,7 +334,7 @@ StableAttachmentPart* WorkerAttachment::getAttachment(FbStatusVector* status, Da
301334

302335
MutexUnlockGuard unlock(item->m_mutex, FB_FUNCTION);
303336
status->init();
304-
sAtt = doAttach(status, dbb);
337+
sAtt = item->doAttach(status, dbb);
305338
if (!sAtt)
306339
{
307340
// log error ?
@@ -439,7 +472,7 @@ StableAttachmentPart* WorkerAttachment::doAttach(FbStatusVector* status, Databas
439472
//jInstance->setDbCryptCallback(&status, tdbb->getAttachment()->att_crypt_callback);
440473

441474
if (Config::getServerMode() == MODE_SUPER)
442-
sAtt = WorkerStableAttachment::create(status, dbb, jInstance);
475+
sAtt = WorkerStableAttachment::create(status, dbb, jInstance, this);
443476
else
444477
{
445478
ClumpletWriter dpb(ClumpletReader::Tagged, MAX_DPB_SIZE, isc_dpb_version1);

src/jrd/WorkerAttachment.h

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "firebird.h"
3232
#include "../common/classes/alloc.h"
3333
#include "../common/classes/array.h"
34+
#include "../common/classes/condition.h"
3435
#include "../common/classes/fb_string.h"
3536
#include "../common/classes/GenericMap.h"
3637
#include "../common/classes/init.h"
@@ -43,19 +44,24 @@
4344
namespace Jrd
4445
{
4546

47+
class WorkerAttachment;
48+
4649
class WorkerStableAttachment : public SysStableAttachment
4750
{
4851
public:
49-
static WorkerStableAttachment* create(FbStatusVector* status, Database* dbb, JProvider* provider);
52+
static WorkerStableAttachment* create(FbStatusVector* status, Database* dbb, JProvider* provider,
53+
WorkerAttachment* workers);
5054

5155
void fini();
5256

5357
protected:
5458
virtual void doOnIdleTimer(Firebird::TimerImpl* timer);
5559

5660
private:
57-
explicit WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* att);
61+
explicit WorkerStableAttachment(FbStatusVector* status, Jrd::Attachment* att, WorkerAttachment* workers);
5862
virtual ~WorkerStableAttachment();
63+
64+
WorkerAttachment* m_workers;
5965
};
6066

6167

@@ -77,6 +83,8 @@ class WorkerContextHolder : public Jrd::DatabaseContextHolder, public Jrd::Attac
7783

7884
class WorkerAttachment
7985
{
86+
friend class WorkerStableAttachment;
87+
8088
public:
8189
explicit WorkerAttachment();
8290

@@ -93,10 +101,14 @@ class WorkerAttachment
93101

94102
private:
95103
static WorkerAttachment* getByName(const Firebird::PathName& dbname);
96-
static Jrd::StableAttachmentPart* doAttach(FbStatusVector* status, Jrd::Database* dbb);
104+
Jrd::StableAttachmentPart* doAttach(FbStatusVector* status, Jrd::Database* dbb);
97105
static void doDetach(FbStatusVector* status, Jrd::StableAttachmentPart* sAtt);
98106
void clear(bool checkRefs);
99107

108+
void incWorkers();
109+
void decWorkers();
110+
void waitForWorkers();
111+
100112

101113
typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left<Firebird::PathName, WorkerAttachment*> > >
102114
MapDbIdToWorkAtts;
@@ -109,7 +121,15 @@ class WorkerAttachment
109121
Firebird::HalfStaticArray<Jrd::StableAttachmentPart*, 8> m_idleAtts;
110122
Firebird::SortedArray<Jrd::StableAttachmentPart*,
111123
Firebird::InlineStorage<Jrd::StableAttachmentPart*, 8> > m_activeAtts;
112-
int m_cntUserAtts;
124+
125+
// count of regular user attachments, used with non-shared Database
126+
int m_cntUserAtts = 0;
127+
128+
// count of internal worker attachments, used with shared Database
129+
int m_cntWorkers = 0;
130+
131+
// used to wait for "no internal workers" condition
132+
Firebird::Condition m_noWorkers;
113133
};
114134

115135
} // namespace Jrd

0 commit comments

Comments
 (0)