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
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
b6762c3cce
commit
6749faa584
@ -47,6 +47,11 @@ namespace Firebird
|
||||
return refCnt;
|
||||
}
|
||||
|
||||
void assertNonZero()
|
||||
{
|
||||
fb_assert(m_refCnt.value() > 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
RefCounted() : m_refCnt(0) {}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user