Skip to content

Commit

Permalink
Fixed CORE-4185: related issues with crypt thread start/stop
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexPeshkoff committed Sep 9, 2013
1 parent 0bee401 commit edd2f69
Showing 1 changed file with 60 additions and 6 deletions.
66 changes: 60 additions & 6 deletions src/jrd/CryptoManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "../jrd/pag_proto.h"
#include "../common/isc_proto.h"
#include "../common/classes/GetPlugins.h"
#include "../common/classes/RefMutex.h"

using namespace Firebird;

Expand Down Expand Up @@ -302,11 +303,26 @@ namespace Jrd {

void CryptoManager::startCryptThread(thread_db* tdbb)
{
MutexLockGuard guard(cryptThreadMtx, FB_FUNCTION);
// Try to take crypt mutex
// If can't take that mutex - nothing to do, cryptThread already runs in our process
MutexEnsureUnlock guard(cryptThreadMtx, FB_FUNCTION);
if (!guard.tryEnter())
{
return;
}

// Take exclusive threadLock
// If can't take that lock - nothing to do, cryptThread already runs somewhere
if (LCK_lock(tdbb, threadLock, LCK_EX, LCK_NO_WAIT))
if (!LCK_lock(tdbb, threadLock, LCK_EX, LCK_NO_WAIT))
{
// Cleanup lock manager error
fb_utils::init_status(tdbb->tdbb_status_vector);

return;
}

bool releasingLock = false;
try
{
// Cleanup resources
terminateCryptThread(tdbb);
Expand All @@ -317,6 +333,7 @@ namespace Jrd {
process = hdr->hdr_flags & Ods::hdr_crypt_process ? true : false;
if (!process)
{
releasingLock = true;
LCK_release(tdbb, threadLock);
return;
}
Expand All @@ -325,13 +342,27 @@ namespace Jrd {
// Refresh encryption flag
crypt = hdr->hdr_flags & Ods::hdr_encrypted ? true : false;

// If we are going to start crypt thread, we really need plugin to be loaded
// If we are going to start crypt thread, we need plugin to be loaded
loadPlugin(hdr->hdr_crypt_plugin);

// ready to go
guard.leave(); // release in advance to avoid races with cryptThread()
Thread::start(cryptThreadStatic, (THREAD_ENTRY_PARAM) this, 0, &cryptThreadId);
}
fb_utils::init_status(tdbb->tdbb_status_vector);
catch (const Firebird::Exception&)
{
if (!releasingLock) // avoid secondary exception in catch
{
try
{
LCK_release(tdbb, threadLock);
}
catch (const Firebird::Exception&)
{ }
}

throw;
}
}

void CryptoManager::attach(thread_db* tdbb, Attachment* att)
Expand All @@ -345,7 +376,13 @@ namespace Jrd {

try
{
MutexLockGuard guard(cryptThreadMtx, FB_FUNCTION);
// Try to take crypt mutex
// If can't take that mutex - nothing to do, cryptThread already runs in our process
MutexEnsureUnlock guard(cryptThreadMtx, FB_FUNCTION);
if (!guard.tryEnter())
{
return;
}

// establish context
UserId user;
Expand All @@ -363,6 +400,14 @@ namespace Jrd {
ULONG lastPage = getLastPage(tdbb);
ULONG runpage = 1;
Stack<ULONG> pages;

// Take exclusive threadLock
// If can't take that lock - nothing to do, cryptThread already runs somewhere
if (!LCK_lock(tdbb, threadLock, LCK_EX, LCK_NO_WAIT))
{
return;
}

bool lckRelease = false;

try
Expand Down Expand Up @@ -419,6 +464,12 @@ namespace Jrd {
// At this moment of time all pages with number < lastpage
// are guaranteed to change crypt state. Check for added pages.
lastPage = getLastPage(tdbb);

// forced terminate
if (down)
{
break;
}
} while (runpage < lastPage);

// Finalize crypt
Expand All @@ -438,7 +489,10 @@ namespace Jrd {
if (!lckRelease)
{
// try to save current state of crypt thread
writeDbHeader(tdbb, runpage, pages);
if (!down)
{
writeDbHeader(tdbb, runpage, pages);
}

// Release exclusive lock on StartCryptThread
LCK_release(tdbb, threadLock);
Expand Down

0 comments on commit edd2f69

Please sign in to comment.