From 774d08720b2230ed29d0569fb607cba8ce285967 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 13 May 2011 11:35:03 +0100 Subject: [PATCH 5/7] DBusPendingCall: optionally trace refcount changes --- dbus/dbus-pending-call.c | 72 ++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 66 insertions(+), 6 deletions(-) diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c index 5eeb620..52c393b 100644 --- a/dbus/dbus-pending-call.c +++ b/dbus/dbus-pending-call.c @@ -30,6 +30,7 @@ #include "dbus-list.h" #include "dbus-threads.h" #include "dbus-test.h" +#include "dbus-valgrind-internal.h" /** * @defgroup DBusPendingCallInternals DBusPendingCall implementation details @@ -79,6 +80,47 @@ struct DBusPendingCall unsigned int timeout_added : 1; /**< Have added the timeout */ }; +#ifdef DBUS_ENABLE_VERBOSE_MODE +static void +_dbus_pending_call_trace_ref (DBusPendingCall *pending_call, + int old_refcount, + int new_refcount, + const char *why) +{ + static int enabled = -1; + + if (enabled < 0) + { + const char *s = _dbus_getenv ("DBUS_PENDING_CALL_TRACE"); + + enabled = FALSE; + + if (s && *s) + { + if (*s == '0') + enabled = FALSE; + else if (*s == '1') + enabled = TRUE; + else + _dbus_warn ("DBUS_PENDING_CALL_TRACE should be 0 or 1 if set, " + "not '%s'", s); + } + } + + if (enabled) + { + if (RUNNING_ON_VALGRIND) + VALGRIND_PRINTF_BACKTRACE ("DBusPendingCall %p %d -> %d refs (%s)", + pending_call, old_refcount, new_refcount, why); + else + _dbus_verbose ("DBusPendingCall %p %d -> %d refs (%s)", + pending_call, old_refcount, new_refcount, why); + } +} +#else +#define _dbus_pending_call_trace_ref(p,o,n,w) do {} while (0) +#endif + static dbus_int32_t notify_user_data_slot = -1; /** @@ -140,7 +182,9 @@ _dbus_pending_call_new_unlocked (DBusConnection *connection, _dbus_connection_ref_unlocked (pending->connection); _dbus_data_slot_list_init (&pending->slot_list); - + + _dbus_pending_call_trace_ref (pending, 0, 1, "new_unlocked"); + return pending; } @@ -375,7 +419,13 @@ _dbus_pending_call_set_timeout_error_unlocked (DBusPendingCall *pending, DBusPendingCall * _dbus_pending_call_ref_unlocked (DBusPendingCall *pending) { - _dbus_atomic_inc (&pending->refcount); + dbus_int32_t old_refcount; + + old_refcount = _dbus_atomic_inc (&pending->refcount); + _dbus_pending_call_trace_ref (pending, old_refcount, old_refcount + 1, + "ref_unlocked"); + /* unused if not verbose */ + (void) old_refcount; return pending; } @@ -438,6 +488,8 @@ _dbus_pending_call_unref_and_unlock (DBusPendingCall *pending) old_refcount = _dbus_atomic_dec (&pending->refcount); _dbus_assert (old_refcount > 0); + _dbus_pending_call_trace_ref (pending, old_refcount, + old_refcount - 1, "unref_and_unlock"); CONNECTION_UNLOCK (pending->connection); @@ -552,9 +604,15 @@ _dbus_pending_call_set_data_unlocked (DBusPendingCall *pending, DBusPendingCall * dbus_pending_call_ref (DBusPendingCall *pending) { + dbus_int32_t old_refcount; + _dbus_return_val_if_fail (pending != NULL, NULL); - _dbus_atomic_inc (&pending->refcount); + old_refcount = _dbus_atomic_inc (&pending->refcount); + _dbus_pending_call_trace_ref (pending, old_refcount, old_refcount + 1, + "ref"); + /* unused if not verbose */ + (void) old_refcount; return pending; } @@ -568,13 +626,15 @@ dbus_pending_call_ref (DBusPendingCall *pending) void dbus_pending_call_unref (DBusPendingCall *pending) { - dbus_bool_t last_unref; + dbus_int32_t old_refcount; _dbus_return_if_fail (pending != NULL); - last_unref = (_dbus_atomic_dec (&pending->refcount) == 1); + old_refcount = _dbus_atomic_dec (&pending->refcount); + _dbus_pending_call_trace_ref (pending, old_refcount, old_refcount - 1, + "unref"); - if (last_unref) + if (old_refcount == 1) _dbus_pending_call_last_unref(pending); } -- 1.7.5.4