From 5a73027642b826793658774df8a0536975120b19 Mon Sep 17 00:00:00 2001
From: John Eckersberg <jeckersb@redhat.com>
Date: Fri, 11 Oct 2019 08:59:41 -0400
Subject: [PATCH] Fix: libcrmservice: try not to spam close() file descriptors
With large file descriptor limits, action_launch_child can close
millions of non-existent file descriptors.
Instead, try to read open file descriptors from /proc or /dev/fd and
close only those which are open.
See rhbz#1762025
---
lib/services/services_linux.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/lib/services/services_linux.c b/lib/services/services_linux.c
index 90c1f44..464fc5b 100644
--- a/lib/services/services_linux.c
+++ b/lib/services/services_linux.c
@@ -445,6 +445,7 @@ static void
action_launch_child(svc_action_t *op)
{
int lpc;
+ DIR *dir;
/* SIGPIPE is ignored (which is different from signal blocking) by the gnutls library.
* Depending on the libqb version in use, libqb may set SIGPIPE to be ignored as well.
@@ -476,8 +477,29 @@ action_launch_child(svc_action_t *op)
setpgid(0, 0);
// Close all file descriptors except stdin/stdout/stderr
- for (lpc = getdtablesize() - 1; lpc > STDERR_FILENO; lpc--) {
- close(lpc);
+#if SUPPORT_PROCFS
+ dir = opendir("/proc/self/fd");
+#else
+ dir = opendir("/dev/fd");
+#endif
+ if (dir == NULL) { /* /proc or /dev/fd not available */
+ /* Iterate over all possible fds, might be slow */
+ for (lpc = getdtablesize() - 1; lpc > STDERR_FILENO; lpc--) {
+ close(lpc);
+ }
+ } else {
+ /* Iterate over fds obtained from /proc or /dev/fd */
+ struct dirent *entry;
+ int dir_fd = dirfd(dir);
+
+ while ((entry = readdir(dir)) != NULL) {
+ lpc = atoi(entry->d_name);
+ if (lpc > STDERR_FILENO && lpc != dir_fd) {
+ close(lpc);
+ }
+ }
+
+ closedir(dir);
}
#if SUPPORT_CIBSECRETS
--
1.8.3.1