8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 20:03:02 +01:00

Fixed #7626: Segfault when new attachment is done to shutting down database
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
AlexPeshkoff 2023-07-06 13:22:10 +03:00
parent b6762c3cce
commit 6749faa584
3 changed files with 59 additions and 0 deletions

View File

@ -47,6 +47,11 @@ namespace Firebird
return refCnt;
}
void assertNonZero()
{
fb_assert(m_refCnt.value() > 0);
}
protected:
RefCounted() : m_refCnt(0) {}

View File

@ -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

View File

@ -1644,6 +1644,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
@ -1757,6 +1758,7 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
}
EngineContextHolder tdbb(user_status, jAtt, FB_FUNCTION, AttachmentHolder::ATT_DONT_LOCK);
lateBlocking.lock(jAtt->getStable()->getBlockingMutex(), jAtt->getStable());
attachment->att_crypt_callback = getDefCryptCallback(cryptCallback);
attachment->att_client_charset = attachment->att_charset = options.dpb_interp;
@ -2789,6 +2791,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
{
@ -2903,6 +2906,7 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
dbbGuard.lock(SYNC_EXCLUSIVE);
EngineContextHolder tdbb(user_status, jAtt, FB_FUNCTION, AttachmentHolder::ATT_DONT_LOCK);
lateBlocking.lock(jAtt->getStable()->getBlockingMutex(), jAtt->getStable());
attachment->att_crypt_callback = getDefCryptCallback(cryptCallback);