From 0c6d705f5cad4ade389deda8c36e9c217c707285 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 28 Jul 2011 05:33:46 +0200 Subject: [PATCH] sysdeps-unix: introduce dbus_close_all() and make use of it where appropriate This is optimized on Linux and enumerates through /proc/self/fd with a fallback on brute-force closing of fds, in case /proc is not available. --- dbus/dbus-sysdeps-unix.c | 77 +++++++++++++++++++++++++++++++++++++++------ dbus/dbus-sysdeps-unix.h | 2 + 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 03d8524..c587462 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -3124,7 +3124,6 @@ _read_subprocess_line_argv (const char *progpath, int ret; int status; int orig_len; - int i; dbus_bool_t retval; sigset_t new_set, old_set; @@ -3177,7 +3176,6 @@ _read_subprocess_line_argv (const char *progpath, if (pid == 0) { /* child process */ - int maxfds; int fd; fd = open ("/dev/null", O_RDWR); @@ -3201,15 +3199,7 @@ _read_subprocess_line_argv (const char *progpath, if (dup2 (errors_pipe[WRITE_END], 2) == -1) _exit (1); - maxfds = sysconf (_SC_OPEN_MAX); - /* Pick something reasonable if for some reason sysconf - * says unlimited. - */ - if (maxfds < 0) - maxfds = 1024; - /* close all inherited fds */ - for (i = 3; i < maxfds; i++) - close (i); + _dbus_close_all (); sigprocmask (SIG_SETMASK, &old_set, NULL); @@ -3940,4 +3930,69 @@ _dbus_replace_install_prefix (const char *configure_time_path) return configure_time_path; } +/** + * Closes all file descriptors except the first three (i.e. stdin, + * stdout, stderr). + */ +void +_dbus_close_all (void) +{ + int maxfds, i; + +#ifdef __linux__ + DIR *d; + + /* On Linux we can optimize this a bit if /proc is available. If it + isn't available, fall back to the brute force way. */ + + d = opendir ("/proc/self/fd"); + if (d) + { + for (;;) + { + struct dirent buf, *de; + int k, fd; + long l; + char *e = NULL; + + k = readdir_r (d, &buf, &de); + if (k != 0 || !de) + break; + + if (de->d_name[0] == '.') + continue; + + errno = 0; + l = strtol (de->d_name, &e, 10); + if (errno != 0 || e == NULL || *e != '\0') + continue; + + fd = (int) l; + if (fd < 3) + continue; + + if (fd == dirfd (d)) + continue; + + close (fd); + } + + closedir (d); + return; + } +#endif + + maxfds = sysconf (_SC_OPEN_MAX); + + /* Pick something reasonable if for some reason sysconf says + * unlimited. + */ + if (maxfds < 0) + maxfds = 1024; + + /* close all inherited fds */ + for (i = 3; i < maxfds; i++) + close (i); +} + /* tests in dbus-sysdeps-util.c */ diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h index 9f92dcd..fbe5259 100644 --- a/dbus/dbus-sysdeps-unix.h +++ b/dbus/dbus-sysdeps-unix.h @@ -132,6 +132,8 @@ dbus_uid_t _dbus_geteuid (void); dbus_bool_t _dbus_parse_uid (const DBusString *uid_str, dbus_uid_t *uid); +void _dbus_close_all (void); + /** @} */ DBUS_END_DECLS -- 1.7.9