diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index d9ab5e1ea2452131c2778acca6ad913ad4b333af..fd5ec7805fdcaedf73c3fa6aaa1a35970cf8e6db 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -1032,7 +1032,6 @@ void FileClose(File file) { Vfd *vfdP; - struct stat filestats; Assert(FileIsValid(file)); @@ -1055,15 +1054,36 @@ FileClose(File file) } /* - * Delete the file if it was temporary + * Delete the file if it was temporary, and make a log entry if wanted */ if (vfdP->fdstate & FD_TEMPORARY) { - /* reset flag so that die() interrupt won't cause problems */ + /* + * If we get an error, as could happen within the ereport/elog calls, + * we'll come right back here during transaction abort. Reset the + * flag to ensure that we can't get into an infinite loop. This code + * is arranged to ensure that the worst-case consequence is failing + * to emit log message(s), not failing to attempt the unlink. + */ vfdP->fdstate &= ~FD_TEMPORARY; + if (log_temp_files >= 0) { - if (stat(vfdP->fileName, &filestats) == 0) + struct stat filestats; + int stat_errno; + + /* first try the stat() */ + if (stat(vfdP->fileName, &filestats)) + stat_errno = errno; + else + stat_errno = 0; + + /* in any case do the unlink */ + if (unlink(vfdP->fileName)) + elog(LOG, "could not unlink file \"%s\": %m", vfdP->fileName); + + /* and last report the stat results */ + if (stat_errno == 0) { if ((filestats.st_size / 1024) >= log_temp_files) ereport(LOG, @@ -1072,10 +1092,17 @@ FileClose(File file) (unsigned long) filestats.st_size))); } else + { + errno = stat_errno; elog(LOG, "could not stat file \"%s\": %m", vfdP->fileName); + } + } + else + { + /* easy case, just do the unlink */ + if (unlink(vfdP->fileName)) + elog(LOG, "could not unlink file \"%s\": %m", vfdP->fileName); } - if (unlink(vfdP->fileName)) - elog(LOG, "could not unlink file \"%s\": %m", vfdP->fileName); } /* Unregister it from the resource owner */