diff --git a/daemon/call.c b/daemon/call.c index 4e817c4a7..4bd978fde 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -5524,32 +5524,40 @@ call_t *call_get(const str *callid) { } // obtain a reference to a second call while holding a lock to another call -// may intermittently release lock on the first call! +// intermittently releases lock on the first call! // return return another reference to the same call call_t *call_get2(call_t *call1, const str *callid2) { - call_t *ret; + call_t *ret = NULL; + + rwlock_unlock_w(&call1->master_lock); while (true) { RWLOCK_R(&rtpe_callhash_lock); ret = t_hash_table_lookup(rtpe_callhash, callid2); if (!ret) - return NULL; + goto out; if (ret == call1) { obj_hold(ret); - return ret; + goto out; } + rwlock_lock_w(&call1->master_lock); + if (!rwlock_trylock_w(&ret->master_lock)) { obj_hold(ret); return ret; } - // try again after releasing lock rwlock_unlock_w(&call1->master_lock); - rwlock_lock_w(&call1->master_lock); + // try again } + +out: + rwlock_lock_w(&call1->master_lock); + + return ret; } static gboolean fragment_move(str *key, fragment_q *q, void *c) {