In AtEOXact_Files, complain if any files remain unclosed at commit.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 28 Apr 2018 21:45:02 +0000 (17:45 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 28 Apr 2018 21:45:02 +0000 (17:45 -0400)
This change makes this module act more like most of our other low-level
resource management modules.  It's a caller error if something is not
explicitly closed by the end of a successful transaction, so issue
a WARNING about it.  This would not actually have caught the file leak
bug fixed in commit 231bcd080, because that was in a transaction-abort
path; but it still seems like a good, and pretty cheap, cross-check.

Discussion: https://postgr.es/m/152056616579.4966.583293218357089052@wrigleys.postgresql.org

src/backend/access/transam/xact.c
src/backend/postmaster/autovacuum.c
src/backend/postmaster/bgwriter.c
src/backend/postmaster/checkpointer.c
src/backend/postmaster/walwriter.c
src/backend/storage/file/fd.c
src/include/storage/fd.h

index c38de0c5fe981503e2f3ad3ce085987465d609f2..f4e5ea84b996d175da06f4ea0fa2cf6c4026737f 100644 (file)
@@ -2123,7 +2123,7 @@ CommitTransaction(void)
    AtEOXact_on_commit_actions(true);
    AtEOXact_Namespace(true, is_parallel_worker);
    AtEOXact_SMgr();
-   AtEOXact_Files();
+   AtEOXact_Files(true);
    AtEOXact_ComboCid();
    AtEOXact_HashTables(true);
    AtEOXact_PgStat(true);
@@ -2401,7 +2401,7 @@ PrepareTransaction(void)
    AtEOXact_on_commit_actions(true);
    AtEOXact_Namespace(true, false);
    AtEOXact_SMgr();
-   AtEOXact_Files();
+   AtEOXact_Files(true);
    AtEOXact_ComboCid();
    AtEOXact_HashTables(true);
    /* don't call AtEOXact_PgStat here; we fixed pgstat state above */
@@ -2603,7 +2603,7 @@ AbortTransaction(void)
        AtEOXact_on_commit_actions(false);
        AtEOXact_Namespace(false, is_parallel_worker);
        AtEOXact_SMgr();
-       AtEOXact_Files();
+       AtEOXact_Files(false);
        AtEOXact_ComboCid();
        AtEOXact_HashTables(false);
        AtEOXact_PgStat(false);
index 3b90b16daecd86022718fa54846815df2c9863f1..02e6d8131e09882b3916ca067bb890afa2f4a900 100644 (file)
@@ -531,7 +531,7 @@ AutoVacLauncherMain(int argc, char *argv[])
        }
        AtEOXact_Buffers(false);
        AtEOXact_SMgr();
-       AtEOXact_Files();
+       AtEOXact_Files(false);
        AtEOXact_HashTables(false);
 
        /*
index b7813d7a4fb5865dc5ab8a3e6420bb6b59f95d8d..d5ce685e54f7f98c15ee7fabd5d1b24c8e061fb9 100644 (file)
@@ -198,7 +198,7 @@ BackgroundWriterMain(void)
        /* we needn't bother with the other ResourceOwnerRelease phases */
        AtEOXact_Buffers(false);
        AtEOXact_SMgr();
-       AtEOXact_Files();
+       AtEOXact_Files(false);
        AtEOXact_HashTables(false);
 
        /*
index 4b452e7cee63083c9fb123a63a1aee053efae4d5..0950ada6019e20a17728c4ac7f48033603297e13 100644 (file)
@@ -282,7 +282,7 @@ CheckpointerMain(void)
        /* we needn't bother with the other ResourceOwnerRelease phases */
        AtEOXact_Buffers(false);
        AtEOXact_SMgr();
-       AtEOXact_Files();
+       AtEOXact_Files(false);
        AtEOXact_HashTables(false);
 
        /* Warn any waiting backends that the checkpoint failed. */
index 4fa3a3b0aafd9e8fb6e4ecf9f2e84264d8b8410f..688d5b5b80bf8728c9558d54c2929aa6aeef62b0 100644 (file)
@@ -179,7 +179,7 @@ WalWriterMain(void)
        /* we needn't bother with the other ResourceOwnerRelease phases */
        AtEOXact_Buffers(false);
        AtEOXact_SMgr();
-       AtEOXact_Files();
+       AtEOXact_Files(false);
        AtEOXact_HashTables(false);
 
        /*
index f772dfe93f757644c1da0e03156d48022db0bf1c..afce5dadc0993cdaae753a72f01fe05b01635dcf 100644 (file)
@@ -314,7 +314,7 @@ static bool reserveAllocatedDesc(void);
 static int FreeDesc(AllocateDesc *desc);
 
 static void AtProcExit_Files(int code, Datum arg);
-static void CleanupTempFiles(bool isProcExit);
+static void CleanupTempFiles(bool isCommit, bool isProcExit);
 static void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok,
                       bool unlink_all);
 static void RemovePgTempRelationFiles(const char *tsdirname);
@@ -2902,17 +2902,19 @@ AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
 /*
  * AtEOXact_Files
  *
- * This routine is called during transaction commit or abort (it doesn't
- * particularly care which).  All still-open per-transaction temporary file
- * VFDs are closed, which also causes the underlying files to be deleted
- * (although they should've been closed already by the ResourceOwner
- * cleanup). Furthermore, all "allocated" stdio files are closed. We also
- * forget any transaction-local temp tablespace list.
+ * This routine is called during transaction commit or abort.  All still-open
+ * per-transaction temporary file VFDs are closed, which also causes the
+ * underlying files to be deleted (although they should've been closed already
+ * by the ResourceOwner cleanup). Furthermore, all "allocated" stdio files are
+ * closed. We also forget any transaction-local temp tablespace list.
+ *
+ * The isCommit flag is used only to decide whether to emit warnings about
+ * unclosed files.
  */
 void
-AtEOXact_Files(void)
+AtEOXact_Files(bool isCommit)
 {
-   CleanupTempFiles(false);
+   CleanupTempFiles(isCommit, false);
    tempTableSpaces = NULL;
    numTempTableSpaces = -1;
 }
@@ -2926,12 +2928,15 @@ AtEOXact_Files(void)
 static void
 AtProcExit_Files(int code, Datum arg)
 {
-   CleanupTempFiles(true);
+   CleanupTempFiles(false, true);
 }
 
 /*
  * Close temporary files and delete their underlying files.
  *
+ * isCommit: if true, this is normal transaction commit, and we don't
+ * expect any remaining files; warn if there are some.
+ *
  * isProcExit: if true, this is being called as the backend process is
  * exiting. If that's the case, we should remove all temporary files; if
  * that's not the case, we are being called for transaction commit/abort
@@ -2939,7 +2944,7 @@ AtProcExit_Files(int code, Datum arg)
  * also clean up "allocated" stdio files, dirs and fds.
  */
 static void
-CleanupTempFiles(bool isProcExit)
+CleanupTempFiles(bool isCommit, bool isProcExit)
 {
    Index       i;
 
@@ -2979,6 +2984,11 @@ CleanupTempFiles(bool isProcExit)
        have_xact_temporary_files = false;
    }
 
+   /* Complain if any allocated files remain open at commit. */
+   if (isCommit && numAllocatedDescs > 0)
+       elog(WARNING, "%d temporary files and directories not closed at end-of-transaction",
+            numAllocatedDescs);
+
    /* Clean up "allocated" stdio files, dirs and fds. */
    while (numAllocatedDescs > 0)
        FreeDesc(&allocatedDescs[0]);
index 484339b7690f297bb7ea33947264df0ff7894666..548a832be94e081bcd6c48e0c0f71205daafd1c3 100644 (file)
@@ -123,7 +123,7 @@ extern void SetTempTablespaces(Oid *tableSpaces, int numSpaces);
 extern bool TempTablespacesAreSet(void);
 extern int GetTempTablespaces(Oid *tableSpaces, int numSpaces);
 extern Oid GetNextTempTableSpace(void);
-extern void AtEOXact_Files(void);
+extern void AtEOXact_Files(bool isCommit);
 extern void AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
                  SubTransactionId parentSubid);
 extern void RemovePgTempFiles(void);