From 3752f3c6202824f843967b81eae8ea92604ac1db 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 appropirate 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 | 76 ++++++++++++++++++++++++++++++++++++++++------ dbus/dbus-sysdeps-unix.h | 2 + 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 5cd1e10..6c3c66d 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -3096,7 +3096,6 @@ _read_subprocess_line_argv (const char *progpath, if (pid == 0) { /* child process */ - int maxfds; int fd; fd = open ("/dev/null", O_RDWR); @@ -3120,15 +3119,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); @@ -3870,4 +3861,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 200ec8a..0e0bab3 100644 --- a/dbus/dbus-sysdeps-unix.h +++ b/dbus/dbus-sysdeps-unix.h @@ -133,6 +133,8 @@ dbus_gid_t _dbus_getgid (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.6