Fix count_usable_fds() to stop trying to open files once it reaches
authorTom Lane
Sun, 7 Aug 2005 18:47:19 +0000 (18:47 +0000)
committerTom Lane
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 11c7b8076650f0088b99836ea9ad5963413acf68..2fb8165d2f2257d21bfca15449a06603b59ca61e 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);