[PATCH] Make ENOSPC not fatal in semaphore creation

From: mp39590(at)gmail(dot)com
To: pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: [PATCH] Make ENOSPC not fatal in semaphore creation
Date: 2021-10-17 14:11:28
Message-ID: 20211017141128.26728-1-mp39590@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

From: Mikhail <mp39590(at)gmail(dot)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

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2021-10-17 14:29:24 Re: [PATCH] Make ENOSPC not fatal in semaphore creation
Previous Message Simon Riggs 2021-10-17 11:00:24 Re: Next Steps with Hash Indexes