[PATCH] s-s-d: use close_range if possible

Mix <[email protected]>
Newsgroups gmane.linux.debian.devel.dpkg.general
Message-ID <TYSPR04MB8429C5FD9AD30479A9B006E1C5652@TYSPR04MB8429.apcprd04.prod.outlook.com>
This commit introduces a new `close_all_fds` function in s-s-d to close all file
descriptors prior to starting a new process. The function leverages the
`close_range` system call if it is supported (available in glibc >= 2.34 and
kernel >= 5.9). If `close_range` is not available, the function falls back to
iterating over each file descriptor individually.

These changes address the issue where s-s-d could freeze when the system has a
relatively high `max_fds` setting.
---
this change might be useful for systems with a high `max_fds` setting, i was
found this problem while trying to run s-s-d in docker container since it have
default max_fds set to 1073741816 and it will take a long time to close all fds

maybe this patch should be backported to previous version of s-s-d?

 configure.ac              |  1 +
 utils/start-stop-daemon.c | 25 ++++++++++++++++++-------
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/configure.ac b/configure.ac
index 3f1a86362..faed01518 100644
--- a/configure.ac
+++ b/configure.ac
@@ -213,6 +213,7 @@ AC_CHECK_FUNCS([\
 AC_CHECK_FUNCS([\
   setsid \
   getdtablesize \
+  close_range \
   getprocs64 \
   getprogname \
   getexecname \
diff --git a/utils/start-stop-daemon.c b/utils/start-stop-daemon.c
index 8899f0c03..029733b0e 100644
--- a/utils/start-stop-daemon.c
+++ b/utils/start-stop-daemon.c
@@ -496,14 +496,26 @@ parse_unsigned(const char *string, int base, int *value_r)
 	return 0;
 }
 
-static long
-get_open_fd_max(void)
+static void
+close_all_fds(void)
 {
+	long max_fd;
+	int close_range_ret = ENOSYS;
+
 #ifdef HAVE_GETDTABLESIZE
-	return getdtablesize();
+	max_fd = getdtablesize();
 #else
-	return sysconf(_SC_OPEN_MAX);
+	max_fd = sysconf(_SC_OPEN_MAX);
 #endif
+
+#ifdef HAVE_CLOSE_RANGE
+	close_range_ret = close_range(3, max_fd, 0);
+#endif
+	if (close_range_ret == ENOSYS) {
+		long fd;
+		for (fd = max_fd - 1; fd >= 3; fd--)
+			close(fd);
+	}
 }
 
 #ifndef HAVE_SETSID
@@ -2664,9 +2676,8 @@ do_start(int argc, char **argv)
 
 		dup2(devnull_fd, 0); /* stdin */
 
-		 /* Now close all extra fds. */
-		for (i = get_open_fd_max() - 1; i >= 3; --i)
-			close(i);
+		/* Now close all extra fds. */
+		close_all_fds();
 	}
 	execv(startas, argv);
 	fatale("unable to start %s", startas);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.