From 0ba41e071c157e96d796a506ddcc73268f2b7a0c Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sat, 29 Jun 2019 15:59:51 +0100 Subject: [PATCH 1/3] Move _dbus_check_fdleaks_* from dbus-message-util to tests This is only called from test code. Signed-off-by: Simon McVittie --- dbus/dbus-message-internal.h | 4 - dbus/dbus-message-util.c | 142 +---------------------------- test/internals/dbus-message-util.c | 2 + test/test-utils.c | 127 +++++++++++++++++++++++++- test/test-utils.h | 7 +- 5 files changed, 135 insertions(+), 147 deletions(-) diff --git a/dbus/dbus-message-internal.h b/dbus/dbus-message-internal.h index f73d3146..adc07f98 100644 --- a/dbus/dbus-message-internal.h +++ b/dbus/dbus-message-internal.h @@ -143,10 +143,6 @@ _dbus_clear_variant (DBusVariant **variant_p) _dbus_clear_pointer_impl (DBusVariant, variant_p, _dbus_variant_free); } -typedef struct DBusInitialFDs DBusInitialFDs; -DBusInitialFDs *_dbus_check_fdleaks_enter (void); -void _dbus_check_fdleaks_leave (DBusInitialFDs *fds); - DBUS_END_DECLS #endif /* DBUS_MESSAGE_INTERNAL_H */ diff --git a/dbus/dbus-message-util.c b/dbus/dbus-message-util.c index 3ac9437d..d279b1d2 100644 --- a/dbus/dbus-message-util.c +++ b/dbus/dbus-message-util.c @@ -1,9 +1,7 @@ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* dbus-message-util.c Would be in dbus-message.c, but only used by bus/tests * - * Copyright 2009 Red Hat, Inc. - * Copyright 2011-2017 Collabora Ltd. - * Copyright 2017 Endless Mobile, Inc. + * Copyright 2017 Collabora Ltd. * * Licensed under the Academic Free License version 2.1 * @@ -25,23 +23,7 @@ #include -#include "dbus-internals.h" -#include "dbus-test.h" #include "dbus-message-private.h" -#include "dbus-marshal-recursive.h" -#include "dbus-string.h" -#ifdef HAVE_UNIX_FD_PASSING -#include "dbus-sysdeps-unix.h" -#endif -#include - -#ifdef __linux__ -/* Necessary for the Linux-specific fd leak checking code only */ -#include -#include -#include -#include -#endif /** * @addtogroup DBusMessage @@ -63,125 +45,3 @@ _dbus_message_get_n_unix_fds (DBusMessage *message) return 0; #endif } - -#ifdef DBUS_ENABLE_EMBEDDED_TESTS - -#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; - - if (fd >= FD_SETSIZE) - { - _dbus_verbose ("FD %d unexpectedly large; cannot track whether " - "it is leaked\n", fd); - 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 */ - - 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; - - if (fd >= FD_SETSIZE) - { - _dbus_verbose ("FD %d unexpectedly large; cannot track whether " - "it is leaked\n", fd); - continue; - } - - if (FD_ISSET (fd, &fds->set)) - continue; - - _dbus_test_fatal ("file descriptor %i leaked in %s.", fd, __FILE__); - } - - closedir (d); - } - - free (fds); -#else - _dbus_assert (fds == NULL); -#endif -} - -#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/test/internals/dbus-message-util.c b/test/internals/dbus-message-util.c index 2fe1ffd2..3ec62e38 100644 --- a/test/internals/dbus-message-util.c +++ b/test/internals/dbus-message-util.c @@ -46,6 +46,8 @@ #include "dbus-message-factory.h" +#include "test/test-utils.h" + #ifdef DBUS_ENABLE_EMBEDDED_TESTS /** * Reads arguments from a message iterator given a variable argument diff --git a/test/test-utils.c b/test/test-utils.c index 60948a71..1838c0a7 100644 --- a/test/test-utils.c +++ b/test/test-utils.c @@ -1,6 +1,7 @@ /* - * Copyright 2002-2008 Red Hat Inc. + * Copyright 2002-2009 Red Hat Inc. * Copyright 2011-2017 Collabora Ltd. + * Copyright 2017 Endless Mobile, Inc. * * SPDX-License-Identifier: MIT * @@ -46,6 +47,12 @@ # include #endif +#ifdef __linux__ +/* Necessary for the Linux-specific fd leak checking code only */ +#include +#include +#endif + #include "dbus/dbus-message-internal.h" #include "dbus/dbus-test-tap.h" @@ -526,6 +533,124 @@ _dbus_test_append_different_uid (DBusString *uid) #endif /* !defined(DBUS_UNIX) */ +#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; + + if (fd >= FD_SETSIZE) + { + _dbus_verbose ("FD %d unexpectedly large; cannot track whether " + "it is leaked\n", fd); + 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 */ + + 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; + + if (fd >= FD_SETSIZE) + { + _dbus_verbose ("FD %d unexpectedly large; cannot track whether " + "it is leaked\n", fd); + continue; + } + + if (FD_ISSET (fd, &fds->set)) + continue; + + _dbus_test_fatal ("file descriptor %i leaked in %s.", fd, __FILE__); + } + + closedir (d); + } + + free (fds); +#else + _dbus_assert (fds == NULL); +#endif +} + /* * _dbus_test_main: * @argc: number of command-line arguments diff --git a/test/test-utils.h b/test/test-utils.h index 8c3c171f..579fd425 100644 --- a/test/test-utils.h +++ b/test/test-utils.h @@ -1,6 +1,7 @@ /* - * Copyright 2002-2008 Red Hat Inc. + * Copyright 2002-2009 Red Hat Inc. * Copyright 2011-2017 Collabora Ltd. + * Copyright 2017 Endless Mobile, Inc. * * SPDX-License-Identifier: MIT * @@ -96,4 +97,8 @@ _DBUS_WARN_UNUSED_RESULT dbus_bool_t _dbus_test_append_different_username (DBusString *username); #endif +typedef struct DBusInitialFDs DBusInitialFDs; +DBusInitialFDs *_dbus_check_fdleaks_enter (void); +void _dbus_check_fdleaks_leave (DBusInitialFDs *fds); + #endif From 491a2da305dd3847fde6d0d26746addf7b3858f1 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sat, 29 Jun 2019 16:00:06 +0100 Subject: [PATCH 2/3] dbus-message-util: Fix Doxygen annotations Signed-off-by: Simon McVittie --- dbus/dbus-message-util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dbus/dbus-message-util.c b/dbus/dbus-message-util.c index d279b1d2..be8b63d4 100644 --- a/dbus/dbus-message-util.c +++ b/dbus/dbus-message-util.c @@ -26,7 +26,7 @@ #include "dbus-message-private.h" /** - * @addtogroup DBusMessage + * @addtogroup DBusMessageInternals * @{ */ @@ -45,3 +45,5 @@ _dbus_message_get_n_unix_fds (DBusMessage *message) return 0; #endif } + +/** @} */ From e4e904a86b15c6a5ba5648251e316e859f0a748e Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sat, 29 Jun 2019 16:15:55 +0100 Subject: [PATCH 3/3] tests: Improve messages when fd leaks are diagnosed Signed-off-by: Simon McVittie --- dbus/dbus-internals.h | 3 +++ test/internals/dbus-message-util.c | 20 +++++++++++--------- test/test-utils.c | 7 ++++--- test/test-utils.h | 3 ++- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h index 647da6f7..294aef47 100644 --- a/dbus/dbus-internals.h +++ b/dbus/dbus-internals.h @@ -453,6 +453,9 @@ dbus_bool_t _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str, typedef struct { char _assertion[(expr) ? 1 : -1]; } \ _DBUS_PASTE (_DBUS_STATIC_ASSERT_, __LINE__) _DBUS_GNUC_UNUSED +#define _DBUS_STRINGIFY(x) #x +#define _DBUS_FILE_LINE __FILE__ ":" _DBUS_STRINGIFY(__LINE__) + DBUS_END_DECLS #endif /* DBUS_INTERNALS_H */ diff --git a/test/internals/dbus-message-util.c b/test/internals/dbus-message-util.c index 3ec62e38..df2ab8cf 100644 --- a/test/internals/dbus-message-util.c +++ b/test/internals/dbus-message-util.c @@ -884,7 +884,8 @@ verify_test_message (DBusMessage *message) } static void -verify_test_message_args_ignored (DBusMessage *message) +verify_test_message_args_ignored (DBusMessage *message, + const char *context) { DBusMessageIter iter; DBusError error = DBUS_ERROR_INIT; @@ -922,11 +923,12 @@ verify_test_message_args_ignored (DBusMessage *message) _dbus_verbose ("arguments ignored.\n"); } - _dbus_check_fdleaks_leave (initial_fds); + _dbus_check_fdleaks_leave (initial_fds, context); } static void -verify_test_message_memleak (DBusMessage *message) +verify_test_message_memleak (DBusMessage *message, + const char *context) { DBusMessageIter iter; DBusError error = DBUS_ERROR_INIT; @@ -1036,7 +1038,7 @@ verify_test_message_memleak (DBusMessage *message) _dbus_close (our_unix_fd2, &error); #endif } - _dbus_check_fdleaks_leave (initial_fds); + _dbus_check_fdleaks_leave (initial_fds, context); } /** @@ -1501,7 +1503,7 @@ _dbus_message_test (const char *test_data_dir _DBUS_GNUC_UNUSED) _dbus_message_loader_unref (loader); check_memleaks (); - _dbus_check_fdleaks_leave (initial_fds); + _dbus_check_fdleaks_leave (initial_fds, _DBUS_FILE_LINE); initial_fds = _dbus_check_fdleaks_enter (); /* Test enumeration of array elements */ @@ -1623,8 +1625,8 @@ _dbus_message_test (const char *test_data_dir _DBUS_GNUC_UNUSED) _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig)); - verify_test_message_args_ignored (message); - verify_test_message_memleak (message); + verify_test_message_args_ignored (message, _DBUS_FILE_LINE); + verify_test_message_memleak (message, _DBUS_FILE_LINE); dbus_message_unref (message); @@ -1660,7 +1662,7 @@ _dbus_message_test (const char *test_data_dir _DBUS_GNUC_UNUSED) } check_memleaks (); - _dbus_check_fdleaks_leave (initial_fds); + _dbus_check_fdleaks_leave (initial_fds, _DBUS_FILE_LINE); /* Now load every message in test_data_dir if we have one */ if (test_data_dir == NULL) @@ -1671,7 +1673,7 @@ _dbus_message_test (const char *test_data_dir _DBUS_GNUC_UNUSED) if (!foreach_message_file (test_data_dir, try_message_file, NULL)) _dbus_test_fatal ("foreach_message_file test failed"); - _dbus_check_fdleaks_leave (initial_fds); + _dbus_check_fdleaks_leave (initial_fds, _DBUS_FILE_LINE); return TRUE; } diff --git a/test/test-utils.c b/test/test-utils.c index 1838c0a7..28c9bc04 100644 --- a/test/test-utils.c +++ b/test/test-utils.c @@ -597,7 +597,8 @@ _dbus_check_fdleaks_enter (void) } void -_dbus_check_fdleaks_leave (DBusInitialFDs *fds) +_dbus_check_fdleaks_leave (DBusInitialFDs *fds, + const char *context) { #ifdef __linux__ DIR *d; @@ -639,7 +640,7 @@ _dbus_check_fdleaks_leave (DBusInitialFDs *fds) if (FD_ISSET (fd, &fds->set)) continue; - _dbus_test_fatal ("file descriptor %i leaked in %s.", fd, __FILE__); + _dbus_test_fatal ("file descriptor %i leaked in %s.", fd, context); } closedir (d); @@ -775,7 +776,7 @@ _dbus_test_main (int argc, _dbus_test_check_memleaks (tests[i].name); if (flags & DBUS_TEST_FLAGS_CHECK_FD_LEAKS) - _dbus_check_fdleaks_leave (initial_fds); + _dbus_check_fdleaks_leave (initial_fds, tests[i].name); } free (test_data_dir); diff --git a/test/test-utils.h b/test/test-utils.h index 579fd425..eb0d9e24 100644 --- a/test/test-utils.h +++ b/test/test-utils.h @@ -99,6 +99,7 @@ dbus_bool_t _dbus_test_append_different_username (DBusString *username); typedef struct DBusInitialFDs DBusInitialFDs; DBusInitialFDs *_dbus_check_fdleaks_enter (void); -void _dbus_check_fdleaks_leave (DBusInitialFDs *fds); +void _dbus_check_fdleaks_leave (DBusInitialFDs *fds, + const char *context); #endif