Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit79c712a

Browse files
committed
Add code to InternalIpcMemoryCreate() to handle the case where shmget()
returns EINVAL for an existing shared memory segment. Although it's notterribly sensible, that behavior does meet the POSIX spec because EINVALis the appropriate error code when the existing segment is smaller than therequested size, and the spec explicitly disclaims any particular ordering oferror checks. Moreover, it does in fact happen on OS X and probably otherBSD-derived kernels. (We were able to talk NetBSD into changing their code,but purging that behavior from the wild completely seems unlikely to happen.)We need to distinguish collision with a pre-existing segment from invalid sizerequest in order to behave sensibly, so it's worth some extra code here to getit right. Per report from Gavin Kistner and subsequent investigation.Back-patch to all supported versions, since any of them could get usedwith a kernel having the debatable behavior.
1 parent25681e0 commit79c712a

File tree

1 file changed

+43
-1
lines changed

1 file changed

+43
-1
lines changed

‎src/backend/port/sysv_shmem.c

Lines changed: 43 additions & 1 deletion
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-
* $Header: /cvsroot/pgsql/src/backend/port/sysv_shmem.c,v 1.24.2.3 2007/07/02 20:12:21 tgl Exp $
13+
* $Header: /cvsroot/pgsql/src/backend/port/sysv_shmem.c,v 1.24.2.4 2010/05/01 22:47:15 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -85,6 +85,48 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, uint32 size)
8585
)
8686
returnNULL;
8787

88+
/*
89+
* Some BSD-derived kernels are known to return EINVAL, not EEXIST,
90+
* if there is an existing segment but it's smaller than "size"
91+
* (this is a result of poorly-thought-out ordering of error tests).
92+
* To distinguish between collision and invalid size in such cases,
93+
* we make a second try with size = 0. These kernels do not test
94+
* size against SHMMIN in the preexisting-segment case, so we will
95+
* not get EINVAL a second time if there is such a segment.
96+
*/
97+
if (errno==EINVAL)
98+
{
99+
intsave_errno=errno;
100+
101+
shmid=shmget(memKey,0,IPC_CREAT |IPC_EXCL |IPCProtection);
102+
103+
if (shmid<0)
104+
{
105+
/* As above, fail quietly if we verify a collision */
106+
if (errno==EEXIST||errno==EACCES
107+
#ifdefEIDRM
108+
||errno==EIDRM
109+
#endif
110+
)
111+
returnNULL;
112+
/* Otherwise, fall through to report the original error */
113+
}
114+
else
115+
{
116+
/*
117+
* On most platforms we cannot get here because SHMMIN is
118+
* greater than zero. However, if we do succeed in creating
119+
* a zero-size segment, free it and then fall through to
120+
* report the original error.
121+
*/
122+
if (shmctl(shmid,IPC_RMID,NULL)<0)
123+
elog(LOG,"shmctl(%d, %d, 0) failed: %m",
124+
(int)shmid,IPC_RMID);
125+
}
126+
127+
errno=save_errno;
128+
}
129+
88130
/*
89131
* Else complain and abort
90132
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp