diff --git a/daemon/call.c b/daemon/call.c index 566a754..0cc1331 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1316,16 +1316,30 @@ static void call_destroy(struct call *c) { struct callmaster *m = c->callmaster; struct callstream *s; +restart: rwlock_lock_w(&m->hashlock); - g_hash_table_remove(m->callhash, c->callid); /* steal this ref */ + if (c->linked) { + if (!g_hash_table_remove(m->callhash, c->callid)) { + rwlock_unlock_w(&m->hashlock); + goto restart; + } + c->linked = 0; + obj_put(c); + } rwlock_unlock_w(&m->hashlock); if (redis_delete) redis_delete(c, m->conf.redis); + mutex_lock(&c->lock); + if (c->shutdown) + goto out; + c->shutdown = 1; mylog(LOG_INFO, LOG_PREFIX_C "Final packet stats:", c->callid); while (c->callstreams->head) { s = g_queue_pop_head(c->callstreams); + mutex_unlock(&c->lock); + mutex_lock(&s->lock); mylog(LOG_INFO, LOG_PREFIX_C "--- " "side A: " @@ -1344,10 +1358,12 @@ static void call_destroy(struct call *c) { s->peers[1].rtps[1].localport, s->peers[1].rtps[1].stats.packets, s->peers[1].rtps[1].stats.bytes, s->peers[1].rtps[1].stats.errors); kill_callstream(s); + mutex_unlock(&s->lock); obj_put(s); + mutex_lock(&c->lock); } - - obj_put(c); +out: + mutex_unlock(&c->lock); } diff --git a/daemon/call.h b/daemon/call.h index 25ad1aa..b037134 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -93,6 +93,9 @@ struct call { time_t created; GHashTable *infohash; time_t lookup_done; + + int linked:1; + int shutdown:1; }; struct callmaster_config {