FS-3386 add some more debug defines to sofia and avoid double destroy in nh
This commit is contained in:
parent
06fa4eee78
commit
b0e076a74f
|
@ -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, "<app>", 0, "<app>")
|
||||
}
|
||||
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, "<app>", 0, "<app>")
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return _su_home_unref_by((su_home_t *)nh, file, line, function);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue