diff --git a/src/common/ThreadStart.cpp b/src/common/ThreadStart.cpp index 195e3fbffc0..e90a62a24d3 100644 --- a/src/common/ThreadStart.cpp +++ b/src/common/ThreadStart.cpp @@ -219,9 +219,19 @@ ThreadId Thread::getId() #endif } +ThreadId Thread::getIdFromHandle(Handle threadHandle) +{ + return threadHandle; +} + +bool Thread::isCurrent(InternalId iid) +{ + return pthread_equal(iid, pthread_self()); +} + bool Thread::isCurrent() { - return pthread_equal(internalId, pthread_self()); + return isCurrent(internalId); } void Thread::sleep(unsigned milliseconds) @@ -363,9 +373,19 @@ ThreadId Thread::getId() return GetCurrentThreadId(); } +ThreadId Thread::getIdFromHandle(Handle threadHandle) +{ + return GetThreadId(threadHandle); +} + +bool Thread::isCurrent(InternalId iid) +{ + return GetCurrentThreadId() == iid; +} + bool Thread::isCurrent() { - return GetCurrentThreadId() == internalId; + return isCurrent(internalId); } void Thread::sleep(unsigned milliseconds) @@ -410,6 +430,10 @@ Thread::Handle Thread::getId() { } +Thread::Handle Thread::getIdFromHandle(Handle) +{ +} + void Thread::sleep(unsigned milliseconds) { } diff --git a/src/common/ThreadStart.h b/src/common/ThreadStart.h index c962313fd91..25d59638a1d 100644 --- a/src/common/ThreadStart.h +++ b/src/common/ThreadStart.h @@ -83,10 +83,12 @@ class Thread static void kill(Handle& handle); static ThreadId getId(); + static ThreadId getIdFromHandle(Handle threadHandle); static void sleep(unsigned milliseconds); static void yield(); + static bool isCurrent(InternalId iid); bool isCurrent(); Thread() diff --git a/src/jrd/CryptoManager.cpp b/src/jrd/CryptoManager.cpp index b3e17273304..118d0b54158 100644 --- a/src/jrd/CryptoManager.cpp +++ b/src/jrd/CryptoManager.cpp @@ -319,7 +319,7 @@ namespace Jrd { keyConsumers(getPool()), hash(getPool()), dbInfo(FB_NEW DbInfo(this)), - cryptThreadId(0), + cryptThreadHandle(0), cryptPlugin(NULL), checkFactory(NULL), dbb(*tdbb->getDatabase()), @@ -337,8 +337,8 @@ namespace Jrd { CryptoManager::~CryptoManager() { - if (cryptThreadId) - Thread::waitForCompletion(cryptThreadId); + if (cryptThreadHandle) + Thread::waitForCompletion(cryptThreadHandle); delete stateLock; delete threadLock; @@ -925,10 +925,10 @@ namespace Jrd { void CryptoManager::terminateCryptThread(thread_db*, bool wait) { flDown = true; - if (wait && cryptThreadId) + if (wait && cryptThreadHandle) { - Thread::waitForCompletion(cryptThreadId); - cryptThreadId = 0; + Thread::waitForCompletion(cryptThreadHandle); + cryptThreadHandle = 0; } } @@ -987,7 +987,7 @@ namespace Jrd { // ready to go guard.leave(); // release in advance to avoid races with cryptThread() - Thread::start(cryptThreadStatic, (THREAD_ENTRY_PARAM) this, THREAD_medium, &cryptThreadId); + Thread::start(cryptThreadStatic, (THREAD_ENTRY_PARAM) this, THREAD_medium, &cryptThreadHandle); } catch (const Firebird::Exception&) { diff --git a/src/jrd/CryptoManager.h b/src/jrd/CryptoManager.h index 8037e086d9b..ebc0dc8ee38 100644 --- a/src/jrd/CryptoManager.h +++ b/src/jrd/CryptoManager.h @@ -301,6 +301,10 @@ class CryptoManager final : public Firebird::PermanentStorage, public BarSync::I UCHAR getCurrentState(thread_db* tdbb) const; const char* getKeyName() const; const char* getPluginName() const; + Thread::Handle getCryptThreadHandle() const + { + return cryptThreadHandle; + } private: enum IoResult {SUCCESS_ALL, FAILED_CRYPT, FAILED_IO}; @@ -378,7 +382,7 @@ class CryptoManager final : public Firebird::PermanentStorage, public BarSync::I AttachmentsRefHolder keyProviders, keyConsumers; Firebird::string hash; Firebird::RefPtr dbInfo; - Thread::Handle cryptThreadId; + Thread::Handle cryptThreadHandle; Firebird::IDbCryptPlugin* cryptPlugin; Factory* checkFactory; Database& dbb; diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 424ae89e6bc..b60d9fa5ff9 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -7763,14 +7763,26 @@ void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment, XThreadEns Sync sync(&dbb->dbb_sync, "jrd.cpp: release_attachment"); + // dummy mutex is used to avoid races with crypto thread + XThreadMutex dummy_mutex; + XThreadEnsureUnlock dummyGuard(dummy_mutex, FB_FUNCTION); + // avoid races with special threads // take into an account lock earlier taken in DROP DATABASE XThreadEnsureUnlock threadGuard(dbb->dbb_thread_mutex, FB_FUNCTION); XThreadEnsureUnlock* activeThreadGuard = dropGuard; if (!activeThreadGuard) { - threadGuard.enter(); - activeThreadGuard = &threadGuard; + if (dbb->dbb_crypto_manager + && Thread::isCurrent(Thread::getIdFromHandle(dbb->dbb_crypto_manager->getCryptThreadHandle()))) + { + activeThreadGuard = &dummyGuard; + } + else + { + activeThreadGuard = &threadGuard; + } + activeThreadGuard->enter(); } sync.lock(SYNC_EXCLUSIVE);