From 25282054756d9f2743cb6e4702b7de25828455ed Mon Sep 17 00:00:00 2001 From: Rahila Syed Date: Tue, 14 Jan 2025 11:30:36 +0530 Subject: [PATCH] Prevent the error on creating a dsm segment from an interrupt handler. If DSA or DSM segment is attached to or created while a transaction's resource owner is being released, it will throw an error. Check whether the resource owner is being released before adding the segment to that resource owner. --- src/backend/storage/ipc/dsm.c | 25 +++++++++++++++++-------- src/backend/utils/mmgr/dsa.c | 10 ++++++++-- src/backend/utils/resowner/resowner.c | 9 +++++++++ src/include/utils/resowner.h | 1 + 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index f92a52a00e..a62ecdd003 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -934,9 +934,16 @@ void dsm_unpin_mapping(dsm_segment *seg) { Assert(seg->resowner == NULL); - ResourceOwnerEnlarge(CurrentResourceOwner); - seg->resowner = CurrentResourceOwner; - ResourceOwnerRememberDSM(seg->resowner, seg); + + if (CurrentResourceOwner && !IsResourceOwnerReleasing(CurrentResourceOwner)) + { + ResourceOwnerEnlarge(CurrentResourceOwner); + seg->resowner = CurrentResourceOwner; + ResourceOwnerRememberDSM(seg->resowner, seg); + } + else + /* Could not unpin */ + seg->resowner = NULL; } /* @@ -1202,9 +1209,6 @@ dsm_create_descriptor(void) { dsm_segment *seg; - if (CurrentResourceOwner) - ResourceOwnerEnlarge(CurrentResourceOwner); - seg = MemoryContextAlloc(TopMemoryContext, sizeof(dsm_segment)); dlist_push_head(&dsm_segment_list, &seg->node); @@ -1214,9 +1218,14 @@ dsm_create_descriptor(void) seg->mapped_address = NULL; seg->mapped_size = 0; - seg->resowner = CurrentResourceOwner; - if (CurrentResourceOwner) + if (CurrentResourceOwner && !IsResourceOwnerReleasing(CurrentResourceOwner)) + { + ResourceOwnerEnlarge(CurrentResourceOwner); + seg->resowner = CurrentResourceOwner; ResourceOwnerRememberDSM(CurrentResourceOwner, seg); + } + else + seg->resowner = NULL; slist_init(&seg->on_detach); diff --git a/src/backend/utils/mmgr/dsa.c b/src/backend/utils/mmgr/dsa.c index 17d4f7a7a0..7b2c5a4015 100644 --- a/src/backend/utils/mmgr/dsa.c +++ b/src/backend/utils/mmgr/dsa.c @@ -1282,7 +1282,10 @@ create_internal(void *place, size_t size, */ area = palloc(sizeof(dsa_area)); area->control = control; - area->resowner = CurrentResourceOwner; + if (CurrentResourceOwner && !IsResourceOwnerReleasing(CurrentResourceOwner)) + area->resowner = CurrentResourceOwner; + else + area->resowner = NULL; memset(area->segment_maps, 0, sizeof(dsa_segment_map) * DSA_MAX_SEGMENTS); area->high_segment_index = 0; area->freed_segment_counter = 0; @@ -1338,7 +1341,10 @@ attach_internal(void *place, dsm_segment *segment, dsa_handle handle) /* Build the backend-local area object. */ area = palloc(sizeof(dsa_area)); area->control = control; - area->resowner = CurrentResourceOwner; + if (CurrentResourceOwner && !IsResourceOwnerReleasing(CurrentResourceOwner)) + area->resowner = CurrentResourceOwner; + else + area->resowner = NULL; memset(&area->segment_maps[0], 0, sizeof(dsa_segment_map) * DSA_MAX_SEGMENTS); area->high_segment_index = 0; diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c index ac5ca4a765..60752e455d 100644 --- a/src/backend/utils/resowner/resowner.c +++ b/src/backend/utils/resowner/resowner.c @@ -1082,3 +1082,12 @@ ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock) elog(ERROR, "lock reference %p is not owned by resource owner %s", locallock, owner->name); } + +/* + * Returns true if resource owner is being released + */ +bool +IsResourceOwnerReleasing(ResourceOwner owner) +{ + return(owner->releasing); +} diff --git a/src/include/utils/resowner.h b/src/include/utils/resowner.h index e8d452ca7e..dea97b9c0d 100644 --- a/src/include/utils/resowner.h +++ b/src/include/utils/resowner.h @@ -163,5 +163,6 @@ extern void ReleaseAuxProcessResources(bool isCommit); struct LOCALLOCK; extern void ResourceOwnerRememberLock(ResourceOwner owner, struct LOCALLOCK *locallock); extern void ResourceOwnerForgetLock(ResourceOwner owner, struct LOCALLOCK *locallock); +extern bool IsResourceOwnerReleasing(ResourceOwner owner); #endif /* RESOWNER_H */ -- 2.34.1