Skip to content

Commit 01b882f

Browse files
committed
Fix unsafe references to errno within error messaging logic.
Various places were supposing that errno could be expected to hold still within an ereport() nest or similar contexts. This isn't true necessarily, though in some cases it accidentally failed to fail depending on how the compiler chanced to order the subexpressions. This class of thinko explains recent reports of odd failures on clang-built versions, typically missing or inappropriate HINT fields in messages. Problem identified by Christian Kruse, who also submitted the patch this commit is based on. (I fixed a few issues in his patch and found a couple of additional places with the same disease.) Back-patch as appropriate to all supported branches.
1 parent 5525529 commit 01b882f

File tree

2 files changed

+19
-14
lines changed

2 files changed

+19
-14
lines changed

src/backend/port/sysv_sema.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,17 @@ InternalIpcSemaphoreCreate(IpcSemaphoreKey semKey, int numSems)
9494

9595
if (semId < 0)
9696
{
97+
int saved_errno = errno;
98+
9799
/*
98100
* Fail quietly if error indicates a collision with existing set. One
99101
* would expect EEXIST, given that we said IPC_EXCL, but perhaps we
100102
* could get a permission violation instead? Also, EIDRM might occur
101103
* if an old set is slated for destruction but not gone yet.
102104
*/
103-
if (errno == EEXIST || errno == EACCES
105+
if (saved_errno == EEXIST || saved_errno == EACCES
104106
#ifdef EIDRM
105-
|| errno == EIDRM
107+
|| saved_errno == EIDRM
106108
#endif
107109
)
108110
return -1;
@@ -115,7 +117,7 @@ InternalIpcSemaphoreCreate(IpcSemaphoreKey semKey, int numSems)
115117
errdetail("Failed system call was semget(%lu, %d, 0%o).",
116118
(unsigned long) semKey, numSems,
117119
IPC_CREAT | IPC_EXCL | IPCProtection),
118-
(errno == ENOSPC) ?
120+
(saved_errno == ENOSPC) ?
119121
errhint("This error does *not* mean that you have run out of disk space.\n"
120122
"It occurs when either the system limit for the maximum number of "
121123
"semaphore sets (SEMMNI), or the system wide maximum number of "
@@ -141,13 +143,17 @@ IpcSemaphoreInitialize(IpcSemaphoreId semId, int semNum, int value)
141143

142144
semun.val = value;
143145
if (semctl(semId, semNum, SETVAL, semun) < 0)
146+
{
147+
int saved_errno = errno;
148+
144149
ereport(FATAL,
145150
(errmsg_internal("semctl(%d, %d, SETVAL, %d) failed: %m",
146151
semId, semNum, value),
147-
(errno == ERANGE) ?
152+
(saved_errno == ERANGE) ?
148153
errhint("You possibly need to raise your kernel's SEMVMX value to be at least "
149154
"%d. Look into the PostgreSQL documentation for details.",
150155
value) : 0));
156+
}
151157
}
152158

153159
/*

src/backend/port/sysv_shmem.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,17 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
7979

8080
if (shmid < 0)
8181
{
82+
int shmget_errno = errno;
83+
8284
/*
8385
* Fail quietly if error indicates a collision with existing segment.
8486
* One would expect EEXIST, given that we said IPC_EXCL, but perhaps
8587
* we could get a permission violation instead? Also, EIDRM might
8688
* occur if an old seg is slated for destruction but not gone yet.
8789
*/
88-
if (errno == EEXIST || errno == EACCES
90+
if (shmget_errno == EEXIST || shmget_errno == EACCES
8991
#ifdef EIDRM
90-
|| errno == EIDRM
92+
|| shmget_errno == EIDRM
9193
#endif
9294
)
9395
return NULL;
@@ -101,10 +103,8 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
101103
* size against SHMMIN in the preexisting-segment case, so we will
102104
* not get EINVAL a second time if there is such a segment.
103105
*/
104-
if (errno == EINVAL)
106+
if (shmget_errno == EINVAL)
105107
{
106-
int save_errno = errno;
107-
108108
shmid = shmget(memKey, 0, IPC_CREAT | IPC_EXCL | IPCProtection);
109109

110110
if (shmid < 0)
@@ -130,19 +130,18 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
130130
elog(LOG, "shmctl(%d, %d, 0) failed: %m",
131131
(int) shmid, IPC_RMID);
132132
}
133-
134-
errno = save_errno;
135133
}
136134

137135
/*
138136
* Else complain and abort
139137
*/
138+
errno = shmget_errno;
140139
ereport(FATAL,
141140
(errmsg("could not create shared memory segment: %m"),
142141
errdetail("Failed system call was shmget(key=%lu, size=%lu, 0%o).",
143142
(unsigned long) memKey, (unsigned long) size,
144143
IPC_CREAT | IPC_EXCL | IPCProtection),
145-
(errno == EINVAL) ?
144+
(shmget_errno == EINVAL) ?
146145
errhint("This error usually means that PostgreSQL's request for a shared memory "
147146
"segment exceeded your kernel's SHMMAX parameter. You can either "
148147
"reduce the request size or reconfigure the kernel with larger SHMMAX. "
@@ -155,7 +154,7 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
155154
"The PostgreSQL documentation contains more information about shared "
156155
"memory configuration.",
157156
(unsigned long) size, NBuffers, MaxBackends) : 0,
158-
(errno == ENOMEM) ?
157+
(shmget_errno == ENOMEM) ?
159158
errhint("This error usually means that PostgreSQL's request for a shared "
160159
"memory segment exceeded available memory or swap space. "
161160
"To reduce the request size (currently %lu bytes), reduce "
@@ -164,7 +163,7 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
164163
"The PostgreSQL documentation contains more information about shared "
165164
"memory configuration.",
166165
(unsigned long) size, NBuffers, MaxBackends) : 0,
167-
(errno == ENOSPC) ?
166+
(shmget_errno == ENOSPC) ?
168167
errhint("This error does *not* mean that you have run out of disk space. "
169168
"It occurs either if all available shared memory IDs have been taken, "
170169
"in which case you need to raise the SHMMNI parameter in your kernel, "

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy