OSDN Git Service

Fix count_usable_fds() to stop trying to open files once it reaches
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 7 Aug 2005 18:47:19 +0000 (18:47 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 7 Aug 2005 18:47:19 +0000 (18:47 +0000)
max_files_per_process.  Going further than that is just a waste of
cycles, and it seems that current Cygwin does not cope gracefully
with deliberately running the system out of FDs.  Per Andrew Dunstan.

src/backend/storage/file/fd.c

index 11c7b80..2fb8165 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.118 2005/07/04 04:51:48 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.119 2005/08/07 18:47:19 tgl Exp $
  *
  * NOTES:
  *
@@ -300,10 +300,16 @@ pg_fdatasync(int fd)
  * count_usable_fds --- count how many FDs the system will let us open,
  *             and estimate how many are already open.
  *
+ * We stop counting if usable_fds reaches max_to_probe.  Note: a small
+ * value of max_to_probe might result in an underestimate of already_open;
+ * we must fill in any "gaps" in the set of used FDs before the calculation
+ * of already_open will give the right answer.  In practice, max_to_probe
+ * of a couple of dozen should be enough to ensure good results.
+ *
  * We assume stdin (FD 0) is available for dup'ing
  */
 static void
-count_usable_fds(int *usable_fds, int *already_open)
+count_usable_fds(int max_to_probe, int *usable_fds, int *already_open)
 {
        int                *fd;
        int                     size;
@@ -314,7 +320,7 @@ count_usable_fds(int *usable_fds, int *already_open)
        size = 1024;
        fd = (int *) palloc(size * sizeof(int));
 
-       /* dup until failure ... */
+       /* dup until failure or probe limit reached */
        for (;;)
        {
                int                     thisfd;
@@ -337,6 +343,9 @@ count_usable_fds(int *usable_fds, int *already_open)
 
                if (highestfd < thisfd)
                        highestfd = thisfd;
+
+               if (used >= max_to_probe)
+                       break;
        }
 
        /* release the files we opened */
@@ -364,14 +373,16 @@ set_max_safe_fds(void)
        int                     usable_fds;
        int                     already_open;
 
-       /*
-        * We want to set max_safe_fds to MIN(usable_fds,
-        * max_files_per_process - already_open) less the slop factor for
-        * files that are opened without consulting fd.c.  This ensures that
-        * we won't exceed either max_files_per_process or the
-        * experimentally-determined EMFILE limit.
+       /*----------
+        * We want to set max_safe_fds to
+        *                      MIN(usable_fds, max_files_per_process - already_open)
+        * less the slop factor for files that are opened without consulting
+        * fd.c.  This ensures that we won't exceed either max_files_per_process
+        * or the experimentally-determined EMFILE limit.
+        *----------
         */
-       count_usable_fds(&usable_fds, &already_open);
+       count_usable_fds(max_files_per_process,
+                                        &usable_fds, &already_open);
 
        max_safe_fds = Min(usable_fds, max_files_per_process - already_open);