From ead7cba6708502d79c559c67fd204e8df5b3ee99 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Thu, 18 Oct 2018 10:48:18 +1300 Subject: [PATCH] Fix thinko in handling of corrupted DSM control area. If dsm_postmaster_shutdown() determines that the DSM control segment is corrupted, it should still destroy it, otherwise it is leaked. Leaving it mapped in was causing an assertion failure in dsm_postmaster_startup() during crash restart. Reported by build-farm animal peripatus. The root cause of the corrupted segment in that case is not yet known, but that's a separate problem to investigate. Author: Thomas Munro Reviewed-by: Amit Kapila Diagnosed-by: Tom Lane Discussion: https://postgr.es/m/6153.1539806400%40sss.pgh.pa.us --- src/backend/storage/ipc/dsm.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index 9629f22f7af..3521a00798e 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -138,8 +138,7 @@ static void *dsm_control_impl_private = NULL; /* * Start up the dynamic shared memory system. * - * This is called just once during each cluster lifetime, at postmaster - * startup time. + * This is called at postmaster startup time, and again during crash restarts. */ void dsm_postmaster_startup(PGShmemHeader *shim) @@ -334,15 +333,17 @@ dsm_postmaster_shutdown(int code, Datum arg) * control segment while it was dying. In that case, we warn and ignore * the contents of the control segment. This may end up leaving behind * stray shared memory segments, but there's not much we can do about that - * if the metadata is gone. + * if the metadata is gone. We'll still attempt to destroy the segment + * itself. */ - nitems = dsm_control->nitems; if (!dsm_control_segment_sane(dsm_control, dsm_control_mapped_size)) { ereport(LOG, (errmsg("dynamic shared memory control segment is corrupt"))); - return; + nitems = 0; } + else + nitems = dsm_control->nitems; /* Remove any remaining segments. */ for (i = 0; i < nitems; ++i) @@ -371,6 +372,16 @@ dsm_postmaster_shutdown(int code, Datum arg) dsm_impl_op(DSM_OP_DESTROY, dsm_control_handle, 0, &dsm_control_impl_private, &dsm_control_address, &dsm_control_mapped_size, LOG); + + /* + * In the unlikely event that we failed to unmap the segment, we'll just + * forget that we have it mapped so that we can proceed without an + * assertion failure, in case of crash restart. + */ + dsm_control_address = NULL; + dsm_control_mapped_size = 0; + dsm_control_impl_private = NULL; + dsm_control = dsm_control_address; shim->dsm_control = 0; } -- 2.19.1