8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 10:00:38 +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

(cherry picked from commit 6749faa584)
This commit is contained in:
AlexPeshkoff 2023-07-06 13:22:10 +03:00
parent 370b9dd23b
commit aecbdd6c21
3 changed files with 59 additions and 0 deletions

View File

@ -48,6 +48,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

@ -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
@ -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;
@ -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
{
@ -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);