From 39af16dbd035047572198ca6e8631a5306d4879b Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 10 Nov 2023 13:51:56 +0200 Subject: [PATCH 2/3] Fix dsa.c with different resource owners. This fixes the bug with mixing different resource owners, demonstrated by the test case from previous commit. Discussion: https://www.postgresql.org/message-id/11b70743-c5f3-3910-8e5b-dd6c115ff829%40gmail.com --- src/backend/utils/mmgr/dsa.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/backend/utils/mmgr/dsa.c b/src/backend/utils/mmgr/dsa.c index 8d1aace40ac..c32bb58618b 100644 --- a/src/backend/utils/mmgr/dsa.c +++ b/src/backend/utils/mmgr/dsa.c @@ -59,6 +59,7 @@ #include "utils/dsa.h" #include "utils/freepage.h" #include "utils/memutils.h" +#include "utils/resowner.h" /* * The size of the initial DSM segment that backs a dsa_area created by @@ -371,6 +372,13 @@ struct dsa_area /* Has the mapping been pinned? */ bool mapping_pinned; + /* + * All the mappings are owned by this. The dsa_area itself is not directly + * tracked by the ResourceOwner, but the effect is the same. Can be NULL + * for an area that's held open for session lifetime. + */ + ResourceOwner owner; + /* * This backend's array of segment maps, ordered by segment index * corresponding to control->segment_handles. Some of the area's segments @@ -1265,6 +1273,7 @@ create_internal(void *place, size_t size, area = palloc(sizeof(dsa_area)); area->control = control; area->mapping_pinned = false; + area->owner = CurrentResourceOwner; memset(area->segment_maps, 0, sizeof(dsa_segment_map) * DSA_MAX_SEGMENTS); area->high_segment_index = 0; area->freed_segment_counter = 0; @@ -1321,6 +1330,7 @@ attach_internal(void *place, dsm_segment *segment, dsa_handle handle) area = palloc(sizeof(dsa_area)); area->control = control; area->mapping_pinned = false; + area->owner = CurrentResourceOwner; memset(&area->segment_maps[0], 0, sizeof(dsa_segment_map) * DSA_MAX_SEGMENTS); area->high_segment_index = 0; @@ -1743,6 +1753,7 @@ get_segment_by_index(dsa_area *area, dsa_segment_index index) dsm_handle handle; dsm_segment *segment; dsa_segment_map *segment_map; + ResourceOwner oldowner; /* * If we are reached by dsa_free or dsa_get_address, there must be at @@ -1761,7 +1772,10 @@ get_segment_by_index(dsa_area *area, dsa_segment_index index) elog(ERROR, "dsa_area could not attach to a segment that has been freed"); + oldowner = CurrentResourceOwner; + CurrentResourceOwner = area->owner; segment = dsm_attach(handle); + CurrentResourceOwner = oldowner; if (segment == NULL) elog(ERROR, "dsa_area could not attach to segment"); if (area->mapping_pinned) @@ -2067,6 +2081,7 @@ make_new_segment(dsa_area *area, size_t requested_pages) size_t usable_pages; dsa_segment_map *segment_map; dsm_segment *segment; + ResourceOwner oldowner; Assert(LWLockHeldByMe(DSA_AREA_LOCK(area))); @@ -2151,7 +2166,10 @@ make_new_segment(dsa_area *area, size_t requested_pages) } /* Create the segment. */ + oldowner = CurrentResourceOwner; + CurrentResourceOwner = area->owner; segment = dsm_create(total_size, 0); + CurrentResourceOwner = oldowner; if (segment == NULL) return NULL; dsm_pin_segment(segment); -- 2.39.2