Try to avoid semaphore-related test failures on NetBSD/OpenBSD.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 23 Dec 2024 21:46:07 +0000 (16:46 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 23 Dec 2024 21:46:24 +0000 (16:46 -0500)
These two platforms have a remarkably tight default limit on the
number of SysV semaphores in the system: SEMMNS is only 60
out-of-the-box.  Unless manual action is taken to raise that,
we'll only be able to allocate 3 sets of 16 usable semaphores
each, leading to initdb setting max_connections to just 20.
That's problematic because the core regression tests expect
to be able to launch 20 concurrent sessions, leaving us with
no headroom.  This seems to be the cause of intermittent
buildfarm failures on some machines.

While there's no getting around the fact that you'd better raise
SEMMNS for production use on these platforms, it does seem desirable
for "make check" to pass reliably without that.  We can make that
happen, at least for awhile longer, with two small changes:

* Change sysv_sema.c's SEMAS_PER_SET to 19, so that we can eat up
all of the available semas not just most of them.

* Change initdb to make the smallest max_connections value it will
consider be 25 not 20.

As of HEAD this will leave us with four free semaphores (using the
default values for other relevant parameters such as max_wal_senders).
So we won't need to consider this again until we've invented five
more background processes.  Maybe by then we can switch both these
platforms to some other semaphore API.

For the moment, do this only in master; there've not been field
complaints that might justify a back-patch.

Discussion: https://postgr.es/m/db2773a2-aca0-43d0-99c1-060efcd9954e@gmail.com

doc/src/sgml/runtime.sgml
src/backend/port/sysv_sema.c
src/bin/initdb/initdb.c

index 94135e9d5ee36d0ac86b31136f19bc90d7b9552b..8750044852dac8c246c1249decd088f25a91f02e 100644 (file)
@@ -782,19 +782,19 @@ psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No such
        <row>
         <entry><varname>SEMMNI</varname></entry>
         <entry>Maximum number of semaphore identifiers (i.e., sets)</entry>
-        <entry>at least <literal>ceil(num_os_semaphores / 16)</literal> plus room for other applications</entry>
+        <entry>at least <literal>ceil(num_os_semaphores / 19)</literal> plus room for other applications</entry>
        </row>
 
        <row>
         <entry><varname>SEMMNS</varname></entry>
         <entry>Maximum number of semaphores system-wide</entry>
-        <entry><literal>ceil(num_os_semaphores / 16) * 17</literal> plus room for other applications</entry>
+        <entry><literal>ceil(num_os_semaphores / 19) * 20</literal> plus room for other applications</entry>
        </row>
 
        <row>
         <entry><varname>SEMMSL</varname></entry>
         <entry>Maximum number of semaphores per set</entry>
-        <entry>at least 17</entry>
+        <entry>at least 20</entry>
        </row>
 
        <row>
@@ -841,7 +841,7 @@ psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No such
     (<xref linkend="guc-max-connections"/>), allowed autovacuum worker process
     (<xref linkend="guc-autovacuum-max-workers"/>), allowed WAL sender process
     (<xref linkend="guc-max-wal-senders"/>), allowed background
-    process (<xref linkend="guc-max-worker-processes"/>), etc., in sets of 16.
+    process (<xref linkend="guc-max-worker-processes"/>), etc., in sets of 19.
     The runtime-computed parameter <xref linkend="guc-num-os-semaphores"/>
     reports the number of semaphores required.  This parameter can be viewed
     before starting the server with a <command>postgres</command> command like:
@@ -851,17 +851,17 @@ $ <userinput>postgres -D $PGDATA -C num_os_semaphores</userinput>
    </para>
 
    <para>
-    Each set of 16 semaphores will
-    also contain a 17th semaphore which contains a <quote>magic
+    Each set of 19 semaphores will
+    also contain a 20th semaphore which contains a <quote>magic
     number</quote>, to detect collision with semaphore sets used by
     other applications. The maximum number of semaphores in the system
     is set by <varname>SEMMNS</varname>, which consequently must be at least
     as high as <literal>num_os_semaphores</literal> plus one extra for
-    each set of 16 required semaphores (see the formula in <xref
+    each set of 19 required semaphores (see the formula in <xref
     linkend="sysvipc-parameters"/>).  The parameter <varname>SEMMNI</varname>
     determines the limit on the number of semaphore sets that can
     exist on the system at one time.  Hence this parameter must be at
-    least <literal>ceil(num_os_semaphores / 16)</literal>.
+    least <literal>ceil(num_os_semaphores / 19)</literal>.
     Lowering the number
     of allowed connections is a temporary workaround for failures,
     which are usually confusingly worded <quote>No space
index 5b88a92bc9513356960645180350557499ee2ab5..68835723b90a32d7d7c8976db26a47c8a88bfcca 100644 (file)
@@ -50,8 +50,14 @@ typedef int IpcSemaphoreId;      /* semaphore ID returned by semget(2) */
  * we allocate.  It must be *less than* your kernel's SEMMSL (max semaphores
  * per set) parameter, which is often around 25.  (Less than, because we
  * allocate one extra sema in each set for identification purposes.)
+ *
+ * The present value of 19 is chosen with one eye on NetBSD/OpenBSD's default
+ * SEMMNS setting of 60.  Remembering the extra sema per set, this lets us
+ * allocate three sets with 57 useful semaphores before exceeding that, which
+ * is enough to run our core regression tests.  Users of those systems will
+ * still want to raise SEMMNS for any sort of production work, though.
  */
-#define SEMAS_PER_SET  16
+#define SEMAS_PER_SET  19
 
 #define IPCProtection  (0600)  /* access/modify by user only */
 
index 9a91830783edfa1b65373c48a179e80a113d2390..49e8efd21257dac3c7f3cdf86dce16eac6bc52e3 100644 (file)
@@ -1119,7 +1119,7 @@ test_config_settings(void)
 #define MIN_BUFS_FOR_CONNS(nconns) ((nconns) * 10)
 
    static const int trial_conns[] = {
-       100, 50, 40, 30, 20
+       100, 50, 40, 30, 25
    };
    static const int trial_bufs[] = {
        16384, 8192, 4096, 3584, 3072, 2560, 2048, 1536,