diff options
Diffstat (limited to 'dbus/dbus-message-util.c')
-rw-r--r-- | dbus/dbus-message-util.c | 108 |
1 files changed, 101 insertions, 7 deletions
diff --git a/dbus/dbus-message-util.c b/dbus/dbus-message-util.c index 84471a50..a56fcc49 100644 --- a/dbus/dbus-message-util.c +++ b/dbus/dbus-message-util.c @@ -27,6 +27,17 @@ #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 + +#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 @@ -126,6 +137,50 @@ check_memleaks (void) } } +void +_dbus_check_fdleaks(void) +{ + +#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; + + _dbus_warn("file descriptor %i leaked in %s.\n", fd, __FILE__); + _dbus_assert_not_reached("fdleaks"); + } + + closedir(d); + } +#endif +} + static dbus_bool_t check_have_valid_message (DBusMessageLoader *loader) { @@ -895,7 +950,7 @@ verify_test_message (DBusMessage *message) dbus_bool_t _dbus_message_test (const char *test_data_dir) { - DBusMessage *message; + DBusMessage *message, *message_without_unix_fds; DBusMessageLoader *loader; int i; const char *data; @@ -940,6 +995,9 @@ _dbus_message_test (const char *test_data_dir) unsigned char v2_BYTE; dbus_bool_t v_BOOLEAN; DBusMessageIter iter, array_iter, struct_iter; +#ifdef HAVE_UNIX_FD_PASSING + int v_UNIX_FD; +#endif message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService", "/org/freedesktop/TestPath", @@ -1058,6 +1116,9 @@ _dbus_message_test (const char *test_data_dir) v_BOOLEAN = TRUE; v_BYTE = 42; v2_BYTE = 24; +#ifdef HAVE_UNIX_FD_PASSING + v_UNIX_FD = 1; +#endif dbus_message_append_args (message, DBUS_TYPE_INT16, &v_INT16, @@ -1091,6 +1152,7 @@ _dbus_message_test (const char *test_data_dir) _DBUS_N_ELEMENTS (our_boolean_array), DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &v_ARRAY_STRING, _DBUS_N_ELEMENTS (our_string_array), + DBUS_TYPE_INVALID); i = 0; @@ -1125,7 +1187,16 @@ _dbus_message_test (const char *test_data_dir) sig[i++] = DBUS_TYPE_BOOLEAN; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_STRING; - sig[i++] = DBUS_TYPE_INVALID; + + message_without_unix_fds = dbus_message_copy(message); + _dbus_assert(message_without_unix_fds); +#ifdef HAVE_UNIX_FD_PASSING + dbus_message_append_args (message, + DBUS_TYPE_UNIX_FD, &v_UNIX_FD, + DBUS_TYPE_INVALID); + sig[i++] = DBUS_TYPE_UNIX_FD; +#endif + sig[i++] = DBUS_TYPE_INVALID; _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig)); @@ -1202,6 +1273,20 @@ _dbus_message_test (const char *test_data_dir) _dbus_message_loader_return_buffer (loader, buffer, 1); } +#ifdef HAVE_UNIX_FD_PASSING + { + int *unix_fds; + unsigned n_unix_fds; + /* Write unix fd */ + _dbus_message_loader_get_unix_fds(loader, &unix_fds, &n_unix_fds); + _dbus_assert(n_unix_fds > 0); + _dbus_assert(message->n_unix_fds == 1); + unix_fds[0] = _dbus_dup(message->unix_fds[0], NULL); + _dbus_assert(unix_fds[0] >= 0); + _dbus_message_loader_return_unix_fds(loader, unix_fds, 1); + } +#endif + dbus_message_unref (message); /* Now pop back the message */ @@ -1218,7 +1303,14 @@ _dbus_message_test (const char *test_data_dir) if (dbus_message_get_reply_serial (message) != 5678) _dbus_assert_not_reached ("reply serial fields differ"); - verify_test_message (message); + dbus_message_unref (message); + + /* ovveride the serial, since it was reset by dbus_message_copy() */ + dbus_message_set_serial(message_without_unix_fds, 8901); + + dbus_message_lock (message_without_unix_fds); + + verify_test_message (message_without_unix_fds); { /* Marshal and demarshal the message. */ @@ -1229,7 +1321,7 @@ _dbus_message_test (const char *test_data_dir) int len = 0; char garbage_header[DBUS_MINIMUM_HEADER_SIZE] = "xxx"; - if (!dbus_message_marshal (message, &marshalled, &len)) + if (!dbus_message_marshal (message_without_unix_fds, &marshalled, &len)) _dbus_assert_not_reached ("failed to marshal message"); _dbus_assert (len != 0); @@ -1268,10 +1360,11 @@ _dbus_message_test (const char *test_data_dir) _dbus_assert (dbus_message_demarshal_bytes_needed (garbage_header, DBUS_MINIMUM_HEADER_SIZE) == -1); } - dbus_message_unref (message); + dbus_message_unref (message_without_unix_fds); _dbus_message_loader_unref (loader); check_memleaks (); + _dbus_check_fdleaks(); /* Check that we can abandon a container */ message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService", @@ -1333,9 +1426,10 @@ _dbus_message_test (const char *test_data_dir) print_validities_seen (FALSE); print_validities_seen (TRUE); } - + check_memleaks (); - + _dbus_check_fdleaks(); + /* Now load every message in test_data_dir if we have one */ if (test_data_dir == NULL) return TRUE; |