]> granicus.if.org Git - postgresql/commitdiff
Fix fd.c to preserve errno where needed.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 16 May 2013 19:04:31 +0000 (15:04 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 16 May 2013 19:04:31 +0000 (15:04 -0400)
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.

src/backend/storage/file/fd.c

index c31a523857d3faa14b7450a8b215d2fdf0d8c89d..78c7d41ac48d95d6648baa3951563ba9e4ad3496 100644 (file)
@@ -128,9 +128,15 @@ 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)
@@ -703,7 +709,7 @@ LruInsert(File file)
                if (vfdP->fd < 0)
                {
                        DO_DB(elog(LOG, "RE_OPEN FAILED: %d", errno));
-                       return vfdP->fd;
+                       return -1;
                }
                else
                {
@@ -754,7 +760,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? */
 
@@ -911,8 +917,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;
@@ -1554,7 +1563,6 @@ OpenTransientFile(FileName fileName, int fileFlags, int fileMode)
 {
        int                     fd;
 
-
        DO_DB(elog(LOG, "OpenTransientFile: Allocated %d (%s)",
                           numAllocatedDescs, fileName));