[PATCH] Make ENOSPC not fatal in semaphore creation - Mailing list pgsql-hackers

From mp39590@gmail.com
Subject [PATCH] Make ENOSPC not fatal in semaphore creation
Date
Msg-id 20211017141128.26728-1-mp39590@gmail.com
Whole thread Raw
Responses Re: [PATCH] Make ENOSPC not fatal in semaphore creation  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
From: Mikhail <mp39590@gmail.com>

We might be in situation when we have "just enough" semaphores in the
system limit to start but previously crashed unexpectedly, in that case
we won't be able to start again - semget() will return ENOSPC, despite
the semaphores are ours, and we can recycle them, so check this
situation and try to remove the semaphore, if we are unable - give up
and abort.
---
 src/backend/port/sysv_sema.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/src/backend/port/sysv_sema.c b/src/backend/port/sysv_sema.c
index 21c883ba9a..a889591dba 100644
--- a/src/backend/port/sysv_sema.c
+++ b/src/backend/port/sysv_sema.c
@@ -88,10 +88,6 @@ static void ReleaseSemaphores(int status, Datum arg);
  *
  * Attempt to create a new semaphore set with the specified key.
  * Will fail (return -1) if such a set already exists.
- *
- * If we fail with a failure code other than collision-with-existing-set,
- * print out an error and abort.  Other types of errors suggest nonrecoverable
- * problems.
  */
 static IpcSemaphoreId
 InternalIpcSemaphoreCreate(IpcSemaphoreKey semKey, int numSems)
@@ -118,10 +114,33 @@ InternalIpcSemaphoreCreate(IpcSemaphoreKey semKey, int numSems)
             return -1;
 
         /*
-         * Else complain and abort
+         * We might be in situation when we have "just enough" semaphores in the system
+         * limit to start but previously crashed unexpectedly, in that case we won't be
+         * able to start again - semget() will return ENOSPC, despite the semaphores
+         * are ours, and we can recycle them, so check this situation and try to remove
+         * the semaphore, if we are unable - give up and abort.
+         *
+         * We use same semkey for every start - it's gotten from inode number of the
+         * data folder. So on repeated starts we will use the same key.
          */
+        if (saved_errno == ENOSPC)
+        {
+            union semun        semun;
+
+            semId = semget(semKey, 0, 0);
+
+            semun.val = 0;            /* unused, but keep compiler quiet */
+            if (semctl(semId, 0, IPC_RMID, semun) == 0)
+            {
+                /* Recycled - get the same semaphore again */
+                semId = semget(semKey, numSems, IPC_CREAT | IPC_EXCL | IPCProtection);
+
+                return semId;
+            }
+        }
+
         ereport(FATAL,
-                (errmsg("could not create semaphores: %m"),
+                (errmsg("could not create semaphores: %s", strerror(saved_errno)),
                  errdetail("Failed system call was semget(%lu, %d, 0%o).",
                            (unsigned long) semKey, numSems,
                            IPC_CREAT | IPC_EXCL | IPCProtection),
-- 
2.33.0



pgsql-hackers by date:

Previous
From: Simon Riggs
Date:
Subject: Re: Next Steps with Hash Indexes
Next
From: Tom Lane
Date:
Subject: Re: [PATCH] Make ENOSPC not fatal in semaphore creation