summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2011-07-28 05:33:46 +0200
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2012-03-12 16:38:53 +0000
commit1a4d710d67391c1d7be2d7db6313e6c118acc773 (patch)
tree02acd259876314f67b44918ed49b72c2bc11f5ac
parent552ca4d0ce8a59617db16b78698e80897b8b33e4 (diff)
downloaddbus-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.c77
-rw-r--r--dbus/dbus-sysdeps-unix.h2
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