Skip to content

Commit

Permalink
Fixed #7626: Segfault when new attachment is done to shutting down da…
Browse files Browse the repository at this point in the history
…tabase

(cherry picked from commit 6749faa)
  • Loading branch information
AlexPeshkoff committed Jul 6, 2023
1 parent 370b9dd commit aecbdd6
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/common/classes/RefCounted.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ namespace Firebird
return refCnt;
}

void assertNonZero()
{
fb_assert(m_refCnt.value() > 0);
}

protected:
RefCounted() : m_refCnt(0) {}

Expand Down
50 changes: 50 additions & 0 deletions src/common/classes/RefMutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,56 @@ namespace Firebird
typedef EnsureUnlock<Mutex, NotRefCounted> MutexEnsureUnlock;
typedef EnsureUnlock<RefMutex> RefMutexEnsureUnlock;


// Holds mutex lock and reference to data structure, containing that mutex.
// Lock is never taken in ctor, explicit call 'lock()' is needed later.

class LateRefGuard
{
public:
LateRefGuard(const char* aReason)
: m_lock(nullptr), m_ref(nullptr), m_from(aReason)
{ }

void lock(Mutex* aLock, RefCounted* aRef)
{
fb_assert(aLock);
fb_assert(!m_lock);
m_lock = aLock;
fb_assert(aRef);
fb_assert(!m_ref);
m_ref = aRef;

m_lock->enter(m_from);
m_ref->assertNonZero();
m_ref->addRef();
}

~LateRefGuard()
{
try
{
if (m_lock)
m_lock->leave();
if (m_ref)
m_ref->release();
}
catch (const Exception&)
{
DtorException::devHalt();
}
}

private:
// Forbid copying
LateRefGuard(const LateRefGuard&);
LateRefGuard& operator=(const LateRefGuard&);

Mutex* m_lock;
RefCounted* m_ref;
const char* m_from;
};

} // namespace

#endif // CLASSES_REF_MUTEX_H
4 changes: 4 additions & 0 deletions src/jrd/jrd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1628,6 +1628,7 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
PathName org_filename, expanded_name;
bool is_alias = false;
MutexEnsureUnlock guardDbInit(dbInitMutex, FB_FUNCTION);
LateRefGuard lateBlocking(FB_FUNCTION);
Mapping mapping(Mapping::MAP_THROW_NOT_FOUND, cryptCallback);

try
Expand Down Expand Up @@ -1743,6 +1744,7 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
// Don't pass user_status into ctor to keep warnings
EngineContextHolder tdbb(nullptr, jAtt, FB_FUNCTION, AttachmentHolder::ATT_DONT_LOCK);
tdbb->tdbb_status_vector = user_status;
lateBlocking.lock(jAtt->getStable()->getBlockingMutex(), jAtt->getStable());

attachment->att_crypt_callback = getDefCryptCallback(cryptCallback);
attachment->att_client_charset = attachment->att_charset = options.dpb_interp;
Expand Down Expand Up @@ -2798,6 +2800,7 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
bool is_alias = false;
Firebird::RefPtr<const Config> config;
Mapping mapping(Mapping::MAP_THROW_NOT_FOUND, cryptCallback);
LateRefGuard lateBlocking(FB_FUNCTION);

try
{
Expand Down Expand Up @@ -2914,6 +2917,7 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
// Don't pass user_status into ctor to keep warnings
EngineContextHolder tdbb(nullptr, jAtt, FB_FUNCTION, AttachmentHolder::ATT_DONT_LOCK);
tdbb->tdbb_status_vector = user_status;
lateBlocking.lock(jAtt->getStable()->getBlockingMutex(), jAtt->getStable());

attachment->att_crypt_callback = getDefCryptCallback(cryptCallback);

Expand Down

0 comments on commit aecbdd6

Please sign in to comment.