From b0e076a74febf2f4005e2ba7574a44bd803b1208 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 16 Jul 2011 01:01:37 -0500 Subject: [PATCH] FS-3386 add some more debug defines to sofia and avoid double destroy in nh --- .../libsofia-sip-ua/nua/nua_common.c | 46 ++--- .../libsofia-sip-ua/nua/nua_dialog.c | 17 +- .../sofia-sip/libsofia-sip-ua/nua/nua_stack.c | 37 +++- .../sofia-sip/libsofia-sip-ua/nua/nua_stack.h | 3 + .../libsofia-sip-ua/su/sofia-sip/su_alloc.h | 27 +++ libs/sofia-sip/libsofia-sip-ua/su/su_alloc.c | 159 +++++++++++++++--- 6 files changed, 238 insertions(+), 51 deletions(-) diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c index c3ee92d12f..bc842c242d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c @@ -172,10 +172,16 @@ _nua_handle_ref_by(nua_handle_t *nh, char const *file, unsigned line, char const *function) { - if (nh) - SU_DEBUG_0(("%p - nua_handle_ref() => "MOD_ZU" by %s:%u: %s()\n", - nh, su_home_refcount((su_home_t *)nh) + 1, file, line, function)); - return (nua_handle_t *)su_home_ref((su_home_t *)nh); + +#if (HAVE_MEMLEAK_LOG == 1) + if (nh) + SU_DEBUG_0(("%p - nua_handle_ref() => "MOD_ZU" by %s:%u: %s()\n", + nh, su_home_refcount((su_home_t *)nh) + 1, file, line, function)); + return (nua_handle_t *)su_home_ref((su_home_t *)nh); +#else + + return (nua_handle_t *)_su_home_ref_by((su_home_t *)nh, file, line, function); +#endif } int @@ -183,30 +189,24 @@ _nua_handle_unref_by(nua_handle_t *nh, char const *file, unsigned line, char const *function) { - if (nh) { - size_t refcount = su_home_refcount((su_home_t *)nh) - 1; - int freed = su_home_unref((su_home_t *)nh); - if (freed) refcount = 0; - SU_DEBUG_0(("%p - nua_handle_unref() => "MOD_ZU" by %s:%u: %s()\n", - nh, refcount, file, line, function)); - return freed; - } +#if (HAVE_MEMLEAK_LOG == 1) - return 0; -} + if (nh) { + size_t refcount = su_home_refcount((su_home_t *)nh) - 1; + int freed = su_home_unref((su_home_t *)nh); -#if 0 -nua_handle_t *nua_handle_ref(nua_handle_t *nh) -{ - return _nua_handle_ref_by(nh, "", 0, "") -} + if (freed) refcount = 0; + SU_DEBUG_0(("%p - nua_handle_unref() => "MOD_ZU" by %s:%u: %s()\n", + nh, refcount, file, line, function)); + return freed; + } -int nua_handle_unref(nua_handle_t *nh) -{ - return _nua_handle_unref_by(nh, "", 0, "") -} + return 0; +#else + return _su_home_unref_by((su_home_t *)nh, file, line, function); #endif +} #else diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c index b96b1f31c0..d2b7caf66d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c @@ -373,8 +373,11 @@ nua_dialog_usage_remove_at(nua_owner_t *own, nua_client_request_t *cr0, nua_server_request_t *sr0) { + int unref = 0; + nua_dialog_usage_t *du = NULL; + if (*at) { - nua_dialog_usage_t *du = *at; + du = *at; sip_event_t const *o = NULL; nua_client_request_t *cr, *cr_next; nua_server_request_t *sr, *sr_next; @@ -409,8 +412,7 @@ nua_dialog_usage_remove_at(nua_owner_t *own, } } - su_home_unref(own); - su_free(own, du); + unref = 1; } /* Zap dialog if there are no more usages */ @@ -419,11 +421,20 @@ nua_dialog_usage_remove_at(nua_owner_t *own, else if (ds->ds_usage == NULL) { nua_dialog_remove(own, ds, NULL); ds->ds_has_events = 0; + if (unref) { + su_home_unref(own); + su_free(own, du); + } return; } else { nua_dialog_log_usage(own, ds); } + + if (unref) { + su_home_unref(own); + su_free(own, du); + } } static diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c index de4d243990..5fe5d221d1 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c @@ -396,7 +396,9 @@ void nua_application_event(nua_t *dummy, su_msg_r sumsg, nua_ee_data_t *ee) e->e_msg ? sip_object(e->e_msg) : NULL, e->e_tags); - su_msg_destroy(frame->nf_saved); + if (su_msg_is_non_null(frame->nf_saved)) { + su_msg_destroy(frame->nf_saved); + } nua->nua_current = frame->nf_next; } @@ -417,6 +419,23 @@ msg_t *nua_current_request(nua_t const *nua) return NULL; } + +su_msg_t *nua_current_msg(nua_t const *nua, int clear) +{ + if (nua && nua->nua_current && su_msg_is_non_null(nua->nua_current->nf_saved)) { + su_msg_t *r = nua->nua_current->nf_saved[0]; + if (clear) { + nua->nua_current->nf_saved[0] = NULL; + } + return r; + //return su_msg_data(nua->nua_current->nf_saved)->ee_data->e_msg; + + } + + return NULL; +} + + /** Get request message from saved nua event. @NEW_1_12_4. * * @sa nua_save_event(), nua_respond(), NUTAG_WITH_SAVED(), @@ -638,8 +657,10 @@ void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_ee_data_t *ee) nua_stack_respond(nua, nh, e->e_status, e->e_phrase, tags); break; case nua_r_destroy: - nua_stack_destroy_handle(nua, nh, tags); - su_msg_destroy(nua->nua_signal); + if (!nh->nh_destroyed) { + nua_stack_destroy_handle(nua, nh, tags); + su_msg_destroy(nua->nua_signal); + } return; default: break; @@ -912,6 +933,10 @@ nua_handle_t *nh_validate(nua_t *nua, nua_handle_t *maybe) void nua_stack_destroy_handle(nua_t *nua, nua_handle_t *nh, tagi_t const *tags) { + if (nh->nh_destroyed) { + return; + } + if (nh->nh_notifier) nua_stack_terminate(nua, nh, (enum nua_event_e)0, NULL); @@ -949,6 +974,12 @@ void nh_destroy(nua_t *nua, nua_handle_t *nh) { assert(nh); assert(nh != nua->nua_dhandle); + if (nh->nh_destroyed) { + return; + } + + nh->nh_destroyed = 1; + if (nh->nh_notifier) nea_server_destroy(nh->nh_notifier), nh->nh_notifier = NULL; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h index 97c88582a3..ba2d69a53d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h @@ -150,6 +150,7 @@ struct nua_handle_s unsigned nh_ref_by_user:1; /**< Has user used the handle? */ unsigned nh_init:1; /**< Handle has been initialized */ unsigned nh_used_ptags:1; /**< Ptags has been used */ + unsigned nh_destroyed:1; /**< nh_destroy already called */ unsigned :0; nua_dialog_state_t nh_ds[1]; @@ -338,6 +339,8 @@ int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, tagi_t const *tags); +su_msg_t *nua_current_msg(nua_t const *nua, int clear); + void nua_move_event(nua_saved_event_t a[1], nua_saved_event_t b[1]); nua_handle_t *nh_create_handle(nua_t *nua, nua_hmagic_t *hmagic, tagi_t *tags); diff --git a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_alloc.h b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_alloc.h index 8af6ddebd5..8e4815f33e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_alloc.h +++ b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_alloc.h @@ -64,8 +64,33 @@ struct su_home_s { SU_DLL void *su_home_new(isize_t size) __attribute__((__malloc__)); + +#if (defined(HAVE_MEMLEAK_LOG) && (HAVE_MEMLEAK_LOG != 1)) + +int _su_home_mutex_lock(su_home_t *home, const char *file, unsigned int line, const char *function); +int _su_home_mutex_lock(su_home_t *home, const char *file, unsigned int line, const char *function); + +#define su_home_mutex_lock(home) \ + _su_home_mutex_lock((home), __FILE__, __LINE__, __func__) + +#define su_home_mutex_unlock(home) \ + _su_home_mutex_unlock((home), __FILE__, __LINE__, __func__) + + +su_home_t *_su_home_ref_by( + su_home_t *home, char const *file, unsigned line, char const *by); +int _su_home_unref_by( + su_home_t *home, char const *file, unsigned line, char const *by); + +#define su_home_ref(home) \ + _su_home_ref_by((home), __FILE__, __LINE__, __func__) +#define su_home_unref(home) \ + _su_home_unref_by((home), __FILE__, __LINE__, __func__) + +#else SU_DLL void *su_home_ref(su_home_t const *); SU_DLL int su_home_unref(su_home_t *); +#endif SU_DLL size_t su_home_refcount(su_home_t *home); @@ -107,9 +132,11 @@ SU_DLL void su_home_check(su_home_t const *home); SU_DLL int su_home_check_alloc(su_home_t const *home, void const *data); +#if (!defined(HAVE_MEMLEAK_LOG) || (HAVE_MEMLEAK_LOG != 1)) SU_DLL int su_home_mutex_lock(su_home_t *home); SU_DLL int su_home_mutex_unlock(su_home_t *home); +#endif SU_DLL int su_home_lock(su_home_t *home); SU_DLL int su_home_trylock(su_home_t *home); diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_alloc.c b/libs/sofia-sip/libsofia-sip-ua/su/su_alloc.c index 51259ade1a..cc0b9603f5 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_alloc.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_alloc.c @@ -569,28 +569,6 @@ void *su_home_new(isize_t size) return home; } -/** Create a new reference to a home object. */ -void *su_home_ref(su_home_t const *home) -{ - if (home) { - su_block_t *sub = MEMLOCK(home); - - if (sub == NULL || sub->sub_ref == 0) { - assert(sub && sub->sub_ref != 0); - UNLOCK(home); - return NULL; - } - - if (sub->sub_ref != REF_MAX) - sub->sub_ref++; - UNLOCK(home); - } - else - su_seterrno(EFAULT); - - return (void *)home; -} - /** Set destructor function. * * The destructor function is called after the reference count of a @@ -637,6 +615,123 @@ int su_home_desctructor(su_home_t *home, void (*destructor)(void *)) return su_home_destructor(home, destructor); } + +#if (defined(HAVE_MEMLEAK_LOG) && (HAVE_MEMLEAK_LOG != 1)) +#include "sofia-sip/su_debug.h" + + +static void *real_su_home_ref(su_home_t const *home) +{ + if (home) { + su_block_t *sub = MEMLOCK(home); + + if (sub == NULL || sub->sub_ref == 0) { + assert(sub && sub->sub_ref != 0); + UNLOCK(home); + return NULL; + } + + if (sub->sub_ref != REF_MAX) + sub->sub_ref++; + UNLOCK(home); + } + else + su_seterrno(EFAULT); + + return (void *)home; +} + + +static int real_su_home_unref(su_home_t *home) +{ + su_block_t *sub; + + if (home == NULL) + return 0; + + sub = MEMLOCK(home); + + if (sub == NULL) { + /* Xyzzy */ + return 0; + } + else if (sub->sub_ref == REF_MAX) { + UNLOCK(home); + return 0; + } + else if (--sub->sub_ref > 0) { + UNLOCK(home); + return 0; + } + else if (sub->sub_parent) { + su_home_t *parent = sub->sub_parent; + UNLOCK(home); + su_free(parent, home); + return 1; + } + else { + int hauto = sub->sub_hauto; + _su_home_deinit(home); + if (!hauto) + safefree(home); + /* UNLOCK(home); */ + return 1; + } +} + +su_home_t * +_su_home_ref_by(su_home_t *home, + char const *file, unsigned line, + char const *function) +{ + if (home) + SU_DEBUG_0(("%ld %p - su_home_ref() => "MOD_ZU" by %s:%u: %s()\n", pthread_self(), + home, su_home_refcount(home) + 1, file, line, function)); + return (su_home_t *)real_su_home_ref(home); +} + +int +_su_home_unref_by(su_home_t *home, + char const *file, unsigned line, + char const *function) +{ + if (home) { + size_t refcount = su_home_refcount(home) - 1; + int freed = real_su_home_unref(home); + + if (freed) refcount = 0; + SU_DEBUG_0(("%ld %p - su_home_unref() => "MOD_ZU" by %s:%u: %s()\n", pthread_self(), + home, refcount, file, line, function)); + return freed; + } + + return 0; +} +#else + +/** Create a new reference to a home object. */ +void *su_home_ref(su_home_t const *home) +{ + if (home) { + su_block_t *sub = MEMLOCK(home); + + if (sub == NULL || sub->sub_ref == 0) { + assert(sub && sub->sub_ref != 0); + UNLOCK(home); + return NULL; + } + + if (sub->sub_ref != REF_MAX) + sub->sub_ref++; + UNLOCK(home); + } + else + su_seterrno(EFAULT); + + return (void *)home; +} + + /**Unreference a su_home_t object. * * Decrements the reference count on home object and destroys and frees it @@ -683,6 +778,7 @@ int su_home_unref(su_home_t *home) return 1; } } +#endif /** Return reference count of home. */ size_t su_home_refcount(su_home_t *home) @@ -1546,14 +1642,24 @@ int su_home_is_threadsafe(su_home_t const *home) * Otherwise the su_home_mutex_lock() will just increase the reference * count. */ + +#if (defined(HAVE_MEMLEAK_LOG) && (HAVE_MEMLEAK_LOG != 1)) +int _su_home_mutex_lock(su_home_t *home, const char *file, unsigned int line, const char *function) +#else int su_home_mutex_lock(su_home_t *home) +#endif + { int error; if (home == NULL) return su_seterrno(EFAULT); +#if (defined(HAVE_MEMLEAK_LOG) && (HAVE_MEMLEAK_LOG != 1)) + if (home->suh_blocks == NULL || !_su_home_ref_by(home, file, line, function)) +#else if (home->suh_blocks == NULL || !su_home_ref(home)) +#endif return su_seterrno(EINVAL); /* Uninitialized home */ if (!home->suh_lock) @@ -1570,7 +1676,12 @@ int su_home_mutex_lock(su_home_t *home) * * @sa su_home_unlock(). */ + +#if (defined(HAVE_MEMLEAK_LOG) && (HAVE_MEMLEAK_LOG != 1)) +int _su_home_mutex_unlock(su_home_t *home, const char *file, unsigned int line, const char *function) +#else int su_home_mutex_unlock(su_home_t *home) +#endif { if (home == NULL) return su_seterrno(EFAULT); @@ -1584,7 +1695,11 @@ int su_home_mutex_unlock(su_home_t *home) if (home->suh_blocks == NULL) return su_seterrno(EINVAL), -1; /* Uninitialized home */ +#if (defined(HAVE_MEMLEAK_LOG) && (HAVE_MEMLEAK_LOG != 1)) + _su_home_unref_by(home, file, line, function); +#else su_home_unref(home); +#endif return 0; }