Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1c7fe33

Browse files
committed
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.
1 parent 454333a commit 1c7fe33

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

src/backend/port/sysv_shmem.c

+13-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Portions Copyright (c) 1994, Regents of the University of California
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/port/sysv_shmem.c,v 1.50 2007/03/21 14:39:23 mha Exp $
13+
* $PostgreSQL: pgsql/src/backend/port/sysv_shmem.c,v 1.51 2007/07/02 20:11:54 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -220,6 +220,18 @@ PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
220220
if (errno == EACCES)
221221
return false;
222222

223+
/*
224+
* Some Linux kernel versions (in fact, all of them as of July 2007)
225+
* sometimes return EIDRM when EINVAL is correct. The Linux kernel
226+
* actually does not have any internal state that would justify
227+
* returning EIDRM, so we can get away with assuming that EIDRM is
228+
* equivalent to EINVAL on that platform.
229+
*/
230+
#ifdef HAVE_LINUX_EIDRM_BUG
231+
if (errno == EIDRM)
232+
return false;
233+
#endif
234+
223235
/*
224236
* Otherwise, we had better assume that the segment is in use. The
225237
* only likely case is EIDRM, which implies that the segment has been

src/include/port/linux.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,14 @@
1-
/* $PostgreSQL: pgsql/src/include/port/linux.h,v 1.42 2006/10/04 00:30:09 momjian Exp $ */
1+
/* $PostgreSQL: pgsql/src/include/port/linux.h,v 1.43 2007/07/02 20:11:55 tgl Exp $ */
2+
3+
/*
4+
* As of July 2007, all known versions of the Linux kernel will sometimes
5+
* return EIDRM for a shmctl() operation when EINVAL is correct (it happens
6+
* when the low-order 15 bits of the supplied shm ID match the slot number
7+
* assigned to a newer shmem segment). We deal with this by assuming that
8+
* EIDRM means EINVAL in PGSharedMemoryIsInUse(). This is reasonably safe
9+
* since in fact Linux has no excuse for ever returning EIDRM; it doesn't
10+
* track removed segments in a way that would allow distinguishing them from
11+
* private ones. But someday that code might get upgraded, and we'd have
12+
* to have a kernel version test here.
13+
*/
14+
#define HAVE_LINUX_EIDRM_BUG

0 commit comments

Comments
 (0)