At Fri, 20 May 2022 12:00:14 +0900 (JST), Kyotaro Horiguchi 
<horikyota....@gmail.com> wrote in 
> At Thu, 19 May 2022 17:16:03 -0400, Tom Lane <t...@sss.pgh.pa.us> wrote in 
> > Justin Pryzby <pry...@telsasoft.com> writes:
> > > ./tmp_install/usr/local/pgsql/bin/postgres -D 
> > > ./src/test/regress/tmp_check/data -c min_dynamic_shared_memory=1MB
> > > TRAP: FailedAssertion("val > base", File: 
> > > "../../../../src/include/utils/relptr.h", Line: 67, PID: 21912)
> > 
> > Yeah, I see it too.
> > 
> > > It looks like this may be pre-existing problem exposed by
> > > commit e07d4ddc55fdcf82082950b3eb0cd8f728284c9d
> > 
> > Agreed.  Here I see
> > 
> > #5  FreePageManagerInitialize (fpm=fpm@entry=0x7f34b3ddd300, 
> >     base=base@entry=0x7f34b3ddd300 "") at freepage.c:187
> > #6  0x000000000082423e in dsm_shmem_init () at dsm.c:473
> > 
> > so that where we do
> > 
> >     relptr_store(base, fpm->self, fpm);
> > 
> > the "relative" pointer value would have to be zero, making the case
> > indistinguishable from a NULL pointer.  We can either change the
> > caller so that these addresses aren't the same, or give up the
> > ability to store NULL in relptrs ... doesn't seem like a hard call.
> > 
> > One interesting question I didn't look into is why it takes a nondefault
> > value of min_dynamic_shared_memory to expose this bug.
> 
> The path is taken only when a valid value is given to the
> parameter. If we don't use preallocated dsm, it is initialized
> elsewhere.  In those cases the first bytes of the base address (the
> second parameter of FreePageManagerInitialize) are used for
> dsa_segment_header so the relptr won't be zero (!= NULL).
> 
> It can be silenced by wasting the first MAXALIGN bytes of
> dsm_main_space_begin..

Actually, that change doesn't result in wasting of usable memory size
since the change doesn't move the first effective page.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index 9d86bbe872..c67134ec27 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -461,12 +461,19 @@ dsm_shmem_init(void)
 	dsm_main_space_begin = ShmemInitStruct("Preallocated DSM", size, &found);
 	if (!found)
 	{
-		FreePageManager *fpm = (FreePageManager *) dsm_main_space_begin;
+		/*
+		 * fpm cannot be the same with dsm_main_space_begin due to the
+		 * restriction imposed by FreePageManagerInitialize() due to
+		 * relptr. Add MAXALIGN(1) to fpm to live with that restriction.
+		 */
+		int			gap = MAXALIGN(1);
+		FreePageManager *fpm =
+			(FreePageManager *) ((char *)dsm_main_space_begin + gap);
 		size_t		first_page = 0;
 		size_t		pages;
 
 		/* Reserve space for the FreePageManager. */
-		while (first_page * FPM_PAGE_SIZE < sizeof(FreePageManager))
+		while (first_page * FPM_PAGE_SIZE < sizeof(FreePageManager) + gap)
 			++first_page;
 
 		/* Initialize it and give it all the rest of the space. */
diff --git a/src/test/modules/test_misc/t/004_check_min_dsm_size.pl b/src/test/modules/test_misc/t/004_check_min_dsm_size.pl
new file mode 100644
index 0000000000..025dca33e4
--- /dev/null
+++ b/src/test/modules/test_misc/t/004_check_min_dsm_size.pl
@@ -0,0 +1,14 @@
+# Tests of min_dynamic_shared_memory
+
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+my $node = PostgreSQL::Test::Cluster->new('main');
+$node->init;
+$node->append_conf('postgresql.conf', 'min_dynamic_shared_memory = 1MB');
+$node->start;
+pass('check if server can start with min_dynamic_shared_memory');
+done_testing();

Reply via email to