Skip to content

Commit 6ced97e

Browse files
committed
Avoid races in mapping clear delivery init/fini under high load
(cherry picked from commit ed126e2)
1 parent 7778644 commit 6ced97e

File tree

1 file changed

+36
-15
lines changed

1 file changed

+36
-15
lines changed

src/jrd/Mapping.cpp

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -612,14 +612,17 @@ class MappingIpc FB_FINAL : public Firebird::IpcObject
612612

613613
void shutdown()
614614
{
615+
if (!sharedMemory)
616+
return;
617+
MutexLockGuard gLocal(initMutex, FB_FUNCTION);
615618
if (!sharedMemory)
616619
return;
617620

618621
{
619622
Guard gShared(this);
620-
MappingHeader* sMem = sharedMemory->getHeader();
621623

622-
startupSemaphore.tryEnter(5);
624+
MappingHeader* sMem = sharedMemory->getHeader();
625+
fb_assert(sMem->process[process].id);
623626
sMem->process[process].flags &= ~MappingHeader::FLAG_ACTIVE;
624627
(void) // Ignore errors in cleanup
625628
sharedMemory->eventPost(&sMem->process[process].notifyEvent);
@@ -723,32 +726,37 @@ class MappingIpc FB_FINAL : public Firebird::IpcObject
723726
if (sharedMemory)
724727
return;
725728

726-
Arg::StatusVector statusVector;
729+
AutoSharedMemory tempSharedMemory;
727730
try
728731
{
729-
sharedMemory.reset(FB_NEW_POOL(*getDefaultMemoryPool())
732+
tempSharedMemory.reset(FB_NEW_POOL(*getDefaultMemoryPool())
730733
SharedMemory<MappingHeader>("fb_user_mapping", DEFAULT_SIZE, this));
731734
}
732735
catch (const Exception& ex)
733736
{
734-
iscLogException("MappingIpc: Cannot initialize the shared memory region", ex);
737+
StaticStatusVector s;
738+
ex.stuffException(s);
739+
if (!fb_utils::containsErrorCode(s.begin(), isc_instance_conflict))
740+
iscLogException("MappingIpc: Cannot initialize the shared memory region", ex);
735741
throw;
736742
}
737-
fb_assert(sharedMemory->getHeader()->mhb_header_version == MemoryHeader::HEADER_VERSION);
738-
fb_assert(sharedMemory->getHeader()->mhb_version == MAPPING_VERSION);
743+
fb_assert(tempSharedMemory->getHeader()->mhb_header_version == MemoryHeader::HEADER_VERSION);
744+
fb_assert(tempSharedMemory->getHeader()->mhb_version == MAPPING_VERSION);
739745

740-
Guard gShared(this);
746+
Guard gShared(tempSharedMemory);
741747

742-
MappingHeader* sMem = sharedMemory->getHeader();
748+
MappingHeader* sMem = tempSharedMemory->getHeader();
743749

744750
for (process = 0; process < sMem->processes; ++process)
745751
{
746752
if (!(sMem->process[process].flags & MappingHeader::FLAG_ACTIVE))
747753
break;
754+
748755
if (!ISC_check_process_existence(sMem->process[process].id))
749756
{
750-
sharedMemory->eventFini(&sMem->process[process].notifyEvent);
751-
sharedMemory->eventFini(&sMem->process[process].callbackEvent);
757+
tempSharedMemory->eventFini(&sMem->process[process].notifyEvent);
758+
tempSharedMemory->eventFini(&sMem->process[process].callbackEvent);
759+
752760
break;
753761
}
754762
}
@@ -765,6 +773,8 @@ class MappingIpc FB_FINAL : public Firebird::IpcObject
765773

766774
sMem->process[process].id = processId;
767775
sMem->process[process].flags = MappingHeader::FLAG_ACTIVE;
776+
sharedMemory.reset(tempSharedMemory.release());
777+
768778
if (sharedMemory->eventInit(&sMem->process[process].notifyEvent) != FB_SUCCESS)
769779
{
770780
(Arg::Gds(isc_random) << "Error initializing notifyEvent in mapping shared memory").raise();
@@ -783,6 +793,7 @@ class MappingIpc FB_FINAL : public Firebird::IpcObject
783793
sMem->process[process].flags &= ~MappingHeader::FLAG_ACTIVE;
784794
throw;
785795
}
796+
startupSemaphore.enter();
786797
}
787798

788799
void exceptionHandler(const Exception& ex, ThreadFinishSync<MappingIpc*>::ThreadRoutine*)
@@ -864,34 +875,44 @@ class MappingIpc FB_FINAL : public Firebird::IpcObject
864875

865876
class Guard;
866877
friend class Guard;
878+
typedef SharedMemory<MappingHeader> MappingSharedMemory;
879+
typedef AutoPtr<MappingSharedMemory> AutoSharedMemory;
867880

868881
class Guard
869882
{
870883
public:
871884
explicit Guard(MappingIpc* ptr)
885+
: data(ptr->sharedMemory)
886+
{
887+
fb_assert(data);
888+
data->mutexLock();
889+
}
890+
891+
explicit Guard(MappingSharedMemory* ptr)
872892
: data(ptr)
873893
{
874-
data->sharedMemory->mutexLock();
894+
fb_assert(data);
895+
data->mutexLock();
875896
}
876897

877898
~Guard()
878899
{
879-
data->sharedMemory->mutexUnlock();
900+
data->mutexUnlock();
880901
}
881902

882903
private:
883904
Guard(const Guard&);
884905
Guard& operator=(const Guard&);
885906

886-
MappingIpc* const data;
907+
MappingSharedMemory* const data;
887908
};
888909

889910
static void clearDelivery(MappingIpc* mapping)
890911
{
891912
mapping->clearDeliveryThread();
892913
}
893914

894-
AutoPtr<SharedMemory<MappingHeader> > sharedMemory;
915+
AutoSharedMemory sharedMemory;
895916
Mutex initMutex;
896917
const SLONG processId;
897918
unsigned process;

0 commit comments

Comments
 (0)