mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-08 02:08:02 +02:00
Merge branch 'fdleak-diagnostics' into 'master'
Move fd-leak checking from dbus/ into test/, and improve diagnostics See merge request dbus/dbus!120
This commit is contained in:
commit
379eb3a253
6 changed files with 154 additions and 157 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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,26 +23,10 @@
|
|||
|
||||
#include <config.h>
|
||||
|
||||
#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 <dbus/dbus-test-tap.h>
|
||||
|
||||
#ifdef __linux__
|
||||
/* Necessary for the Linux-specific fd leak checking code only */
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup DBusMessage
|
||||
* @addtogroup DBusMessageInternals
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
|
@ -64,124 +46,4 @@ _dbus_message_get_n_unix_fds (DBusMessage *message)
|
|||
#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 */
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -882,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;
|
||||
|
|
@ -920,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;
|
||||
|
|
@ -1034,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1499,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 */
|
||||
|
|
@ -1621,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);
|
||||
|
||||
|
|
@ -1658,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)
|
||||
|
|
@ -1669,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <dbus/dbus-sysdeps-win.h>
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
/* Necessary for the Linux-specific fd leak checking code only */
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "dbus/dbus-message-internal.h"
|
||||
#include "dbus/dbus-test-tap.h"
|
||||
|
||||
|
|
@ -526,6 +533,125 @@ _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,
|
||||
const char *context)
|
||||
{
|
||||
#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, context);
|
||||
}
|
||||
|
||||
closedir (d);
|
||||
}
|
||||
|
||||
free (fds);
|
||||
#else
|
||||
_dbus_assert (fds == NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* _dbus_test_main:
|
||||
* @argc: number of command-line arguments
|
||||
|
|
@ -650,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);
|
||||
|
|
|
|||
|
|
@ -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,9 @@ _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,
|
||||
const char *context);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue