]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Back-patch fix that allows AllocateFile() to return errno=ENFILE/EMFILE
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 23 Sep 2000 23:31:24 +0000 (23:31 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 23 Sep 2000 23:31:24 +0000 (23:31 +0000)
after we are no longer able to close any more VFDs.  This is needed to
avoid postmaster crash under out-of-file-descriptors conditions.

src/backend/storage/file/fd.c

index e3e1ff00e4c53cf5aeba781d36841a4e070b9c95..4db92bc7a9a70984de35f7695830e86adffb5733 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.56 2000/04/12 17:15:35 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.56.2.1 2000/09/23 23:31:24 tgl Exp $
  *
  * NOTES:
  *
@@ -181,7 +181,7 @@ static void Delete(File file);
 static void LruDelete(File file);
 static void Insert(File file);
 static int     LruInsert(File file);
-static void ReleaseLruFile(void);
+static bool ReleaseLruFile(void);
 static File AllocateVfd(void);
 static void FreeVfd(File file);
 
@@ -347,7 +347,10 @@ LruInsert(File file)
        {
 
                while (nfile + numAllocatedFiles >= pg_nofile())
-                       ReleaseLruFile();
+               {
+                       if (! ReleaseLruFile())
+                               break;
+               }
 
                /*
                 * The open could still fail for lack of file descriptors, eg due
@@ -358,9 +361,12 @@ tryAgain:
                vfdP->fd = open(vfdP->fileName, vfdP->fileFlags, vfdP->fileMode);
                if (vfdP->fd < 0 && (errno == EMFILE || errno == ENFILE))
                {
+                       int             save_errno = errno;
+
                        errno = 0;
-                       ReleaseLruFile();
-                       goto tryAgain;
+                       if (ReleaseLruFile())
+                               goto tryAgain;
+                       errno = save_errno;
                }
 
                if (vfdP->fd < 0)
@@ -392,20 +398,22 @@ tryAgain:
        return 0;
 }
 
-static void
+static bool
 ReleaseLruFile()
 {
        DO_DB(elog(DEBUG, "ReleaseLruFile. Opened %d", nfile));
 
-       if (nfile <= 0)
-               elog(ERROR, "ReleaseLruFile: No open files available to be closed");
-
-       /*
-        * There are opened files and so there should be at least one used vfd
-        * in the ring.
-        */
-       Assert(VfdCache[0].lruMoreRecently != 0);
-       LruDelete(VfdCache[0].lruMoreRecently);
+       if (nfile > 0)
+       {
+               /*
+                * There are opened files and so there should be at least one used
+                * vfd in the ring.
+                */
+               Assert(VfdCache[0].lruMoreRecently != 0);
+               LruDelete(VfdCache[0].lruMoreRecently);
+               return true;                    /* freed a file */
+       }
+       return false;                           /* no files available to free */
 }
 
 /*
@@ -612,17 +620,23 @@ fileNameOpenFile(FileName fileName,
        vfdP = &VfdCache[file];
 
        while (nfile + numAllocatedFiles >= pg_nofile())
-               ReleaseLruFile();
+       {
+               if (! ReleaseLruFile())
+                       break;
+       }
 
 tryAgain:
        vfdP->fd = open(fileName, fileFlags, fileMode);
        if (vfdP->fd < 0 && (errno == EMFILE || errno == ENFILE))
        {
+               int             save_errno = errno;
+
                DO_DB(elog(DEBUG, "fileNameOpenFile: not enough descs, retry, er= %d",
                                   errno));
                errno = 0;
-               ReleaseLruFile();
-               goto tryAgain;
+               if (ReleaseLruFile())
+                       goto tryAgain;
+               errno = save_errno;
        }
 
        if (vfdP->fd < 0)
@@ -1004,11 +1018,14 @@ TryAgain:
        {
                if (errno == EMFILE || errno == ENFILE)
                {
+                       int             save_errno = errno;
+
                        DO_DB(elog(DEBUG, "AllocateFile: not enough descs, retry, er= %d",
                                           errno));
                        errno = 0;
-                       ReleaseLruFile();
-                       goto TryAgain;
+                       if (ReleaseLruFile())
+                               goto TryAgain;
+                       errno = save_errno;
                }
        }
        else