summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2013-05-16 15:05:01 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2013-05-16 15:05:01 -0400
commit0ac9f9e9390476bce59dcb713cf47d28a60406a0 (patch)
tree6fd0dad1a34386cd9811500f48d7d3226a1a26ad
parent65d2b4be0c86d6f514a4048c78eb20b202adba17 (diff)
Fix fd.c to preserve errno where needed.
PathNameOpenFile failed to ensure that the correct value of errno was returned to its caller after a failure (because it incorrectly supposed that free() can never change errno). In some cases this would result in a user-visible failure because an expected ENOENT errno was replaced with something else. Bogus EINVAL failures have been observed on OS X, for example. There were also a couple of places that could mangle an important value of errno if FDDEBUG was defined. While the usefulness of that debug support is highly debatable, we might as well make it safe to use, so add errno save/restore logic to the DO_DB macro. Per bug #8167 from Nelson Minar, diagnosed by RhodiumToad. Back-patch to all supported branches.
-rw-r--r--src/backend/storage/file/fd.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 5b7e60a4fd9..05e159bac2f 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -107,9 +107,15 @@ static int max_safe_fds = 32; /* default if not changed */
/* Debugging.... */
#ifdef FDDEBUG
-#define DO_DB(A) A
+#define DO_DB(A) \
+ do { \
+ int _do_db_save_errno = errno; \
+ A; \
+ errno = _do_db_save_errno; \
+ } while (0)
#else
-#define DO_DB(A) /* A */
+#define DO_DB(A) \
+ ((void) 0)
#endif
#define VFD_CLOSED (-1)
@@ -643,7 +649,7 @@ LruInsert(File file)
if (vfdP->fd < 0)
{
DO_DB(elog(LOG, "RE_OPEN FAILED: %d", errno));
- return vfdP->fd;
+ return -1;
}
else
{
@@ -694,7 +700,7 @@ AllocateVfd(void)
Index i;
File file;
- DO_DB(elog(LOG, "AllocateVfd. Size %lu", SizeVfdCache));
+ DO_DB(elog(LOG, "AllocateVfd. Size %lu", (unsigned long) SizeVfdCache));
Assert(SizeVfdCache > 0); /* InitFileAccess not called? */
@@ -851,8 +857,11 @@ PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
if (vfdP->fd < 0)
{
+ int save_errno = errno;
+
FreeVfd(file);
free(fnamecopy);
+ errno = save_errno;
return -1;
}
++nfile;