summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2011-03-14 16:53:23 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2011-04-27 16:28:36 +0100
commite4abc1d1a5657256bc1632477096bf86b08beff8 (patch)
tree0ff6b6e8ea122c2a270da8c3977a6a4ce4d1bb82
parent614ea05b182b3cd142c6ad9da43e65a7113a0ea4 (diff)
Don't report file descriptors as "leaked" if they were already open
This is necessary to run the regression tests under valgrind (if telling it to output to a dedicated fd), gdb, fakeroot etc. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=35173 Reviewed-by: Colin Walters <walters@verbum.org>
-rw-r--r--bus/test-main.c9
-rw-r--r--dbus/dbus-message-private.h5
-rw-r--r--dbus/dbus-message-util.c86
3 files changed, 90 insertions, 10 deletions
diff --git a/bus/test-main.c b/bus/test-main.c
index cab75306..a8039d51 100644
--- a/bus/test-main.c
+++ b/bus/test-main.c
@@ -54,6 +54,8 @@ check_memleaks (const char *name)
}
#endif /* DBUS_BUILD_TESTS */
+static DBusInitialFDs *initial_fds = NULL;
+
static void
test_pre_hook (void)
{
@@ -62,16 +64,21 @@ test_pre_hook (void)
&& (!bus_selinux_pre_init ()
|| !bus_selinux_full_init ()))
die ("could not init selinux support");
+
+ initial_fds = _dbus_check_fdleaks_enter ();
}
static char *progname = "";
+
static void
test_post_hook (void)
{
if (_dbus_getenv ("DBUS_TEST_SELINUX"))
bus_selinux_shutdown ();
check_memleaks (progname);
- _dbus_check_fdleaks();
+
+ _dbus_check_fdleaks_leave (initial_fds);
+ initial_fds = NULL;
}
int
diff --git a/dbus/dbus-message-private.h b/dbus/dbus-message-private.h
index 57888fa5..c5e3b3ea 100644
--- a/dbus/dbus-message-private.h
+++ b/dbus/dbus-message-private.h
@@ -138,8 +138,9 @@ dbus_bool_t _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
int first_arg_type,
va_list var_args);
-
-void _dbus_check_fdleaks(void);
+typedef struct DBusInitialFDs DBusInitialFDs;
+DBusInitialFDs *_dbus_check_fdleaks_enter (void);
+void _dbus_check_fdleaks_leave (DBusInitialFDs *fds);
/** @} */
diff --git a/dbus/dbus-message-util.c b/dbus/dbus-message-util.c
index f972c8a6..2d2b6fec 100644
--- a/dbus/dbus-message-util.c
+++ b/dbus/dbus-message-util.c
@@ -138,12 +138,66 @@ check_memleaks (void)
}
}
-void
-_dbus_check_fdleaks(void)
-{
+#ifdef __linux__
+struct DBusInitialFDs {
+ fd_set set;
+};
+#endif
+DBusInitialFDs *
+_dbus_check_fdleaks_enter (void)
+{
#ifdef __linux__
+ DIR *d;
+ DBusInitialFDs *fds;
+
+ /* this is plain malloc so it won't interfere with leak checking */
+ fds = malloc (sizeof (DBusInitialFDs));
+ _dbus_assert (fds != NULL);
+
+ /* This works on Linux only */
+
+ if ((d = opendir("/proc/self/fd")))
+ {
+ struct dirent *de;
+
+ while ((de = readdir(d)))
+ {
+ long l;
+ char *e = NULL;
+ int fd;
+
+ if (de->d_name[0] == '.')
+ continue;
+
+ errno = 0;
+ l = strtol(de->d_name, &e, 10);
+ _dbus_assert(errno == 0 && e && !*e);
+ fd = (int) l;
+
+ if (fd < 3)
+ continue;
+
+ if (fd == dirfd(d))
+ continue;
+
+ FD_SET (fd, &fds->set);
+ }
+
+ closedir(d);
+ }
+
+ return fds;
+#else
+ return NULL;
+#endif
+}
+
+void
+_dbus_check_fdleaks_leave (DBusInitialFDs *fds)
+{
+#ifdef __linux__
DIR *d;
/* This works on Linux only */
@@ -173,12 +227,19 @@ _dbus_check_fdleaks(void)
if (fd == dirfd(d))
continue;
+ if (FD_ISSET (fd, &fds->set))
+ continue;
+
_dbus_warn("file descriptor %i leaked in %s.\n", fd, __FILE__);
_dbus_assert_not_reached("fdleaks");
}
closedir(d);
}
+
+ free (fds);
+#else
+ _dbus_assert (fds == NULL);
#endif
}
@@ -1000,6 +1061,9 @@ _dbus_message_test (const char *test_data_dir)
int v_UNIX_FD;
#endif
char **decomposed;
+ DBusInitialFDs *initial_fds;
+
+ initial_fds = _dbus_check_fdleaks_enter ();
message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
"/org/freedesktop/TestPath",
@@ -1394,7 +1458,8 @@ _dbus_message_test (const char *test_data_dir)
_dbus_message_loader_unref (loader);
check_memleaks ();
- _dbus_check_fdleaks();
+ _dbus_check_fdleaks_leave (initial_fds);
+ initial_fds = _dbus_check_fdleaks_enter ();
/* Check that we can abandon a container */
message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
@@ -1458,16 +1523,23 @@ _dbus_message_test (const char *test_data_dir)
}
check_memleaks ();
- _dbus_check_fdleaks();
+ _dbus_check_fdleaks_leave (initial_fds);
/* Now load every message in test_data_dir if we have one */
if (test_data_dir == NULL)
return TRUE;
- return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
+ initial_fds = _dbus_check_fdleaks_enter ();
+
+ if (!dbus_internal_do_not_use_foreach_message_file (test_data_dir,
(DBusForeachMessageFileFunc)
dbus_internal_do_not_use_try_message_file,
- NULL);
+ NULL))
+ _dbus_assert_not_reached ("foreach_message_file test failed");
+
+ _dbus_check_fdleaks_leave (initial_fds);
+
+ return TRUE;
}
#endif /* DBUS_BUILD_TESTS */