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
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;
- }
- return 0;
-}
+#if (HAVE_MEMLEAK_LOG == 1)
-#if 0
-nua_handle_t *nua_handle_ref(nua_handle_t *nh)
-{
- return _nua_handle_ref_by(nh, "<app>", 0, "<app>")
-}
+ if (nh) {
+ size_t refcount = su_home_refcount((su_home_t *)nh) - 1;
+ int freed = su_home_unref((su_home_t *)nh);
-int nua_handle_unref(nua_handle_t *nh)
-{
- return _nua_handle_unref_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;
+ }
+
+ return 0;
+#else
+ return _su_home_unref_by((su_home_t *)nh, file, line, function);
#endif
+}
#else
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;
}
}
- su_home_unref(own);
- su_free(own, du);
+ unref = 1;
}
/* Zap dialog if there are no more usages */
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
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;
}
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(),
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;
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);
{
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;
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];
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);
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);
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);
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
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
return 1;
}
}
+#endif
/** Return reference count of home. */
size_t su_home_refcount(su_home_t *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)
*
* @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);
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;
}