aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-07-02 20:12:00 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-07-02 20:12:00 +0000
commit4ece8fd17e8fbec5e9832f0326c244a25b666e0b (patch)
tree36707f168646474dac9de41660f77d79621be5e5 /src/backend
parentb60765944d60abab22a9f15e63671efecb9748f2 (diff)
downloadpostgresql-4ece8fd17e8fbec5e9832f0326c244a25b666e0b.tar.gz
postgresql-4ece8fd17e8fbec5e9832f0326c244a25b666e0b.zip
Fix failure to restart Postgres when Linux kernel returns EIDRM for shmctl().
This is a Linux kernel bug that apparently exists in every extant kernel version: sometimes shmctl() will fail with EIDRM when EINVAL is correct. We were assuming that EIDRM indicates a possible conflict with pre-existing backends, and refusing to start the postmaster when this happens. Fortunately, there does not seem to be any case where Linux can legitimately return EIDRM (it doesn't track shmem segments in a way that would allow that), so we can get away with just assuming that EIDRM means EINVAL on this platform. Per reports from Michael Fuhr and Jon Lapham --- it's a bit surprising we have not seen more reports, actually.
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/port/sysv_shmem.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index f3ff878db61..fbf5a58148e 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -10,7 +10,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/port/sysv_shmem.c,v 1.47 2006/07/14 05:28:28 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/port/sysv_shmem.c,v 1.47.2.1 2007/07/02 20:12:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -224,6 +224,18 @@ PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
return false;
/*
+ * Some Linux kernel versions (in fact, all of them as of July 2007)
+ * sometimes return EIDRM when EINVAL is correct. The Linux kernel
+ * actually does not have any internal state that would justify
+ * returning EIDRM, so we can get away with assuming that EIDRM is
+ * equivalent to EINVAL on that platform.
+ */
+#ifdef HAVE_LINUX_EIDRM_BUG
+ if (errno == EIDRM)
+ return false;
+#endif
+
+ /*
* Otherwise, we had better assume that the segment is in use. The
* only likely case is EIDRM, which implies that the segment has been
* IPC_RMID'd but there are still processes attached to it.