From 5337ad464ef91d811ecafbebf4698eab6b3d8e8d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 7 Aug 2005 18:47:19 +0000 Subject: [PATCH] Fix count_usable_fds() to stop trying to open files once it reaches 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 | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 11c7b80766..2fb8165d2f 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -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); -- 2.11.0