diff options
author | Lennart Poettering <lennart@poettering.net> | 2011-07-28 05:33:46 +0200 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2012-03-12 16:38:53 +0000 |
commit | 1a4d710d67391c1d7be2d7db6313e6c118acc773 (patch) | |
tree | 02acd259876314f67b44918ed49b72c2bc11f5ac | |
parent | 552ca4d0ce8a59617db16b78698e80897b8b33e4 (diff) | |
download | dbus-1a4d710d67391c1d7be2d7db6313e6c118acc773.tar.gz |
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.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=35230
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
-rw-r--r-- | dbus/dbus-sysdeps-unix.c | 77 | ||||
-rw-r--r-- | 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 da3f0350..57708123 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); @@ -3920,4 +3910,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 9f92dcd1..fbe52590 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 |