From: Mikhail <[email protected]>
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