diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 8677752e30dcfa75346cf54e307b6e82733b4866..08662d1fb372c5309e7e56434400bc414f53deeb 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.50 2007/03/21 14:39:23 mha Exp $
+ *	  $PostgreSQL: pgsql/src/backend/port/sysv_shmem.c,v 1.51 2007/07/02 20:11:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -220,6 +220,18 @@ PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
 		if (errno == EACCES)
 			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
diff --git a/src/include/port/linux.h b/src/include/port/linux.h
index 05cba063a9177965687bc02f3966e82539c20f19..c0dab3ea21b73d36e301a965c594bfc7a94ea4bb 100644
--- a/src/include/port/linux.h
+++ b/src/include/port/linux.h
@@ -1 +1,14 @@
-/* $PostgreSQL: pgsql/src/include/port/linux.h,v 1.42 2006/10/04 00:30:09 momjian Exp $ */
+/* $PostgreSQL: pgsql/src/include/port/linux.h,v 1.43 2007/07/02 20:11:55 tgl Exp $ */
+
+/*
+ * As of July 2007, all known versions of the Linux kernel will sometimes
+ * return EIDRM for a shmctl() operation when EINVAL is correct (it happens
+ * when the low-order 15 bits of the supplied shm ID match the slot number
+ * assigned to a newer shmem segment).  We deal with this by assuming that
+ * EIDRM means EINVAL in PGSharedMemoryIsInUse().  This is reasonably safe
+ * since in fact Linux has no excuse for ever returning EIDRM; it doesn't
+ * track removed segments in a way that would allow distinguishing them from
+ * private ones.  But someday that code might get upgraded, and we'd have
+ * to have a kernel version test here.
+ */
+#define HAVE_LINUX_EIDRM_BUG