Skip to content

Commit 71aa480

Browse files
committed
Get rid of shared_record_typmod_registry_worker_detach; it doesn't work.
This code is unsafe, as proven by buildfarm failures, because it tries to access shared memory that might already be gone. It's also unnecessary, because we're about to exit the process anyway and so the record type cache should never be accessed again. The idea was to lay some foundations for someday recycling workers --- which would require attaching to a different shared tupdesc registry --- but that will require considerably more thought. In the meantime let's save some bytes by just removing the nonfunctional code. Problem identification, and proposal to fix by removing functionality from the detach function, by Thomas Munro. I went a bit further by removing the function altogether. Discussion: https://postgr.es/m/E1dsguX-00056N-9x@gemulon.postgresql.org
1 parent 60cd2f8 commit 71aa480

File tree

1 file changed

+9
-65
lines changed

1 file changed

+9
-65
lines changed

src/backend/utils/cache/typcache.c

Lines changed: 9 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,6 @@ static EnumItem *find_enumitem(TypeCacheEnumData *enumdata, Oid arg);
285285
static int enum_oid_cmp(const void *left, const void *right);
286286
static void shared_record_typmod_registry_detach(dsm_segment *segment,
287287
Datum datum);
288-
static void shared_record_typmod_registry_worker_detach(dsm_segment *segment,
289-
Datum datum);
290288
static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc);
291289
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc,
292290
uint32 typmod);
@@ -1768,8 +1766,9 @@ SharedRecordTypmodRegistryAttach(SharedRecordTypmodRegistry *registry)
17681766
* a freshly started parallel worker. If we ever support worker
17691767
* recycling, a worker would need to zap its local cache in between
17701768
* servicing different queries, in order to be able to call this and
1771-
* synchronize typmods with a new leader; see
1772-
* shared_record_typmod_registry_detach().
1769+
* synchronize typmods with a new leader; but that's problematic because
1770+
* we can't be very sure that record-typmod-related state hasn't escaped
1771+
* to anywhere else in the process.
17731772
*/
17741773
Assert(NextRecordTypmod == 0);
17751774

@@ -1788,11 +1787,12 @@ SharedRecordTypmodRegistryAttach(SharedRecordTypmodRegistry *registry)
17881787
MemoryContextSwitchTo(old_context);
17891788

17901789
/*
1791-
* We install a different detach callback that performs a more complete
1792-
* reset of backend local state.
1790+
* Set up detach hook to run at worker exit. Currently this is the same
1791+
* as the leader's detach hook, but in future they might need to be
1792+
* different.
17931793
*/
17941794
on_dsm_detach(CurrentSession->segment,
1795-
shared_record_typmod_registry_worker_detach,
1795+
shared_record_typmod_registry_detach,
17961796
PointerGetDatum(registry));
17971797

17981798
/*
@@ -2353,10 +2353,8 @@ find_or_make_matching_shared_tupledesc(TupleDesc tupdesc)
23532353
}
23542354

23552355
/*
2356-
* Detach hook to forget about the current shared record typmod
2357-
* infrastructure. This is registered directly in leader backends, and
2358-
* reached only in case of error or shutdown. It's also reached indirectly
2359-
* via the worker detach callback below.
2356+
* On-DSM-detach hook to forget about the current shared record typmod
2357+
* infrastructure. This is currently used by both leader and workers.
23602358
*/
23612359
static void
23622360
shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
@@ -2374,57 +2372,3 @@ shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
23742372
}
23752373
CurrentSession->shared_typmod_registry = NULL;
23762374
}
2377-
2378-
/*
2379-
* Deatch hook allowing workers to disconnect from shared record typmod
2380-
* registry. The resulting state should allow a worker to attach to a
2381-
* different leader, if worker reuse pools are invented.
2382-
*/
2383-
static void
2384-
shared_record_typmod_registry_worker_detach(dsm_segment *segment, Datum datum)
2385-
{
2386-
/*
2387-
* Forget everything we learned about record typmods as part of the
2388-
* session we are disconnecting from, and return to the initial state.
2389-
*/
2390-
if (RecordCacheArray != NULL)
2391-
{
2392-
int32 i;
2393-
2394-
for (i = 0; i < RecordCacheArrayLen; ++i)
2395-
{
2396-
if (RecordCacheArray[i] != NULL)
2397-
{
2398-
TupleDesc tupdesc = RecordCacheArray[i];
2399-
2400-
/*
2401-
* Pointers to tuple descriptors in shared memory are not
2402-
* reference counted, so we are not responsible for freeing
2403-
* them. They'll survive as long as the shared session
2404-
* exists, which should be as long as the owning leader
2405-
* backend exists. In theory we do need to free local
2406-
* reference counted tuple descriptors however, and we can't
2407-
* do that with DescTupleDescRefCount() because we aren't
2408-
* using a resource owner. In practice we don't expect to
2409-
* find any non-shared TupleDesc object in a worker.
2410-
*/
2411-
if (tupdesc->tdrefcount != -1)
2412-
{
2413-
Assert(tupdesc->tdrefcount > 0);
2414-
if (--tupdesc->tdrefcount == 0)
2415-
FreeTupleDesc(tupdesc);
2416-
}
2417-
}
2418-
}
2419-
pfree(RecordCacheArray);
2420-
RecordCacheArray = NULL;
2421-
}
2422-
if (RecordCacheHash != NULL)
2423-
{
2424-
hash_destroy(RecordCacheHash);
2425-
RecordCacheHash = NULL;
2426-
}
2427-
NextRecordTypmod = 0;
2428-
/* Call the code common to leader and worker detach. */
2429-
shared_record_typmod_registry_detach(segment, datum);
2430-
}

0 commit comments

Comments
 (0)