Skip to content

Commit 7aac4d7

Browse files
Fix potential deadlock when starting the encryption thread (#8403)
* add a check to verify thread matching between the encryption thread and the thread where we release the attachment. If they match, use a dummy mutex instead of the actual dbb_thread_mutex to avoid a deadlock * fix Windows build by introducing a method to retrieve thread id from crypto thread handle * rename the crypt process thread id variable to its actual purpose as handle --------- Co-authored-by: aleksey.mochalov <[email protected]>
1 parent 2c5b146 commit 7aac4d7

File tree

5 files changed

+54
-12
lines changed

5 files changed

+54
-12
lines changed

src/common/ThreadStart.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,19 @@ ThreadId Thread::getId()
219219
#endif
220220
}
221221

222+
ThreadId Thread::getIdFromHandle(Handle threadHandle)
223+
{
224+
return threadHandle;
225+
}
226+
227+
bool Thread::isCurrent(InternalId iid)
228+
{
229+
return pthread_equal(iid, pthread_self());
230+
}
231+
222232
bool Thread::isCurrent()
223233
{
224-
return pthread_equal(internalId, pthread_self());
234+
return isCurrent(internalId);
225235
}
226236

227237
void Thread::sleep(unsigned milliseconds)
@@ -363,9 +373,19 @@ ThreadId Thread::getId()
363373
return GetCurrentThreadId();
364374
}
365375

376+
ThreadId Thread::getIdFromHandle(Handle threadHandle)
377+
{
378+
return GetThreadId(threadHandle);
379+
}
380+
381+
bool Thread::isCurrent(InternalId iid)
382+
{
383+
return GetCurrentThreadId() == iid;
384+
}
385+
366386
bool Thread::isCurrent()
367387
{
368-
return GetCurrentThreadId() == internalId;
388+
return isCurrent(internalId);
369389
}
370390

371391
void Thread::sleep(unsigned milliseconds)
@@ -410,6 +430,10 @@ Thread::Handle Thread::getId()
410430
{
411431
}
412432

433+
Thread::Handle Thread::getIdFromHandle(Handle)
434+
{
435+
}
436+
413437
void Thread::sleep(unsigned milliseconds)
414438
{
415439
}

src/common/ThreadStart.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,12 @@ class Thread
8383
static void kill(Handle& handle);
8484

8585
static ThreadId getId();
86+
static ThreadId getIdFromHandle(Handle threadHandle);
8687

8788
static void sleep(unsigned milliseconds);
8889
static void yield();
8990

91+
static bool isCurrent(InternalId iid);
9092
bool isCurrent();
9193

9294
Thread()

src/jrd/CryptoManager.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ namespace Jrd {
319319
keyConsumers(getPool()),
320320
hash(getPool()),
321321
dbInfo(FB_NEW DbInfo(this)),
322-
cryptThreadId(0),
322+
cryptThreadHandle(0),
323323
cryptPlugin(NULL),
324324
checkFactory(NULL),
325325
dbb(*tdbb->getDatabase()),
@@ -337,8 +337,8 @@ namespace Jrd {
337337

338338
CryptoManager::~CryptoManager()
339339
{
340-
if (cryptThreadId)
341-
Thread::waitForCompletion(cryptThreadId);
340+
if (cryptThreadHandle)
341+
Thread::waitForCompletion(cryptThreadHandle);
342342

343343
delete stateLock;
344344
delete threadLock;
@@ -925,10 +925,10 @@ namespace Jrd {
925925
void CryptoManager::terminateCryptThread(thread_db*, bool wait)
926926
{
927927
flDown = true;
928-
if (wait && cryptThreadId)
928+
if (wait && cryptThreadHandle)
929929
{
930-
Thread::waitForCompletion(cryptThreadId);
931-
cryptThreadId = 0;
930+
Thread::waitForCompletion(cryptThreadHandle);
931+
cryptThreadHandle = 0;
932932
}
933933
}
934934

@@ -987,7 +987,7 @@ namespace Jrd {
987987

988988
// ready to go
989989
guard.leave(); // release in advance to avoid races with cryptThread()
990-
Thread::start(cryptThreadStatic, (THREAD_ENTRY_PARAM) this, THREAD_medium, &cryptThreadId);
990+
Thread::start(cryptThreadStatic, (THREAD_ENTRY_PARAM) this, THREAD_medium, &cryptThreadHandle);
991991
}
992992
catch (const Firebird::Exception&)
993993
{

src/jrd/CryptoManager.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,10 @@ class CryptoManager final : public Firebird::PermanentStorage, public BarSync::I
301301
UCHAR getCurrentState(thread_db* tdbb) const;
302302
const char* getKeyName() const;
303303
const char* getPluginName() const;
304+
Thread::Handle getCryptThreadHandle() const
305+
{
306+
return cryptThreadHandle;
307+
}
304308

305309
private:
306310
enum IoResult {SUCCESS_ALL, FAILED_CRYPT, FAILED_IO};
@@ -378,7 +382,7 @@ class CryptoManager final : public Firebird::PermanentStorage, public BarSync::I
378382
AttachmentsRefHolder keyProviders, keyConsumers;
379383
Firebird::string hash;
380384
Firebird::RefPtr<DbInfo> dbInfo;
381-
Thread::Handle cryptThreadId;
385+
Thread::Handle cryptThreadHandle;
382386
Firebird::IDbCryptPlugin* cryptPlugin;
383387
Factory* checkFactory;
384388
Database& dbb;

src/jrd/jrd.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7763,14 +7763,26 @@ void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment, XThreadEns
77637763

77647764
Sync sync(&dbb->dbb_sync, "jrd.cpp: release_attachment");
77657765

7766+
// dummy mutex is used to avoid races with crypto thread
7767+
XThreadMutex dummy_mutex;
7768+
XThreadEnsureUnlock dummyGuard(dummy_mutex, FB_FUNCTION);
7769+
77667770
// avoid races with special threads
77677771
// take into an account lock earlier taken in DROP DATABASE
77687772
XThreadEnsureUnlock threadGuard(dbb->dbb_thread_mutex, FB_FUNCTION);
77697773
XThreadEnsureUnlock* activeThreadGuard = dropGuard;
77707774
if (!activeThreadGuard)
77717775
{
7772-
threadGuard.enter();
7773-
activeThreadGuard = &threadGuard;
7776+
if (dbb->dbb_crypto_manager
7777+
&& Thread::isCurrent(Thread::getIdFromHandle(dbb->dbb_crypto_manager->getCryptThreadHandle())))
7778+
{
7779+
activeThreadGuard = &dummyGuard;
7780+
}
7781+
else
7782+
{
7783+
activeThreadGuard = &threadGuard;
7784+
}
7785+
activeThreadGuard->enter();
77747786
}
77757787

77767788
sync.lock(SYNC_EXCLUSIVE);

0 commit comments

Comments
 (0)