MT#57118 Prevent entire call deletion after `monologue_delete_iter()`

Check globally left monologues (with associations left) after
the `monologue_delete_iter()` has already done its job.

This is needed to prevent cases, when a recursive call of the
`monologue_delete_iter()` leads to blocking of the whole call
destorying, meanwhile it's required, e.g.:
- A is in progress of destorying
- B gets recursive call of `monologue_delete_iter()` and sees
  that A has still one association left with C, which A simply
  hasn't manage to remove yet.

This commit introduces new function: `call_monologues_associations_left()`

Change-Id: I0941c18a76fa8c2a78d3864aee9e6433283bec88
pull/1646/head
Donat Zenichev 3 years ago committed by Víctor Seva
parent 5a51d331b7
commit f4eb2d5a26

@ -4297,8 +4297,8 @@ static unsigned int monologue_delete_iter(struct call_monologue *a, int delete_d
ret |= 0x2;
}
/* first, look at all associated tags: cascade deletion to those which have
* no other associations left */
/* Look into all associated monologues: cascade deletion to those,
* which have no other associations left */
for (GList *l = associated; l; l = l->next)
{
struct call_monologue *b = l->data;
@ -4309,31 +4309,6 @@ static unsigned int monologue_delete_iter(struct call_monologue *a, int delete_d
ret |= 0x1;
}
/* now, if one call object contains some other monologues, which can have own associations,
* not direclty visible for this very monologue,
* then ensure, whether we can afford to destroy the whole call now.
* Maybe some of them still needs a media to flow. */
if (ml_associated_count < call_monologues_count && !(ret & 0x1)) {
for (GList * l = call->monologues.head; l; l = l->next)
{
struct call_monologue * ml = l->data;
/* skip those already checked */
if (g_hash_table_lookup(a->associated_tags, ml))
continue;
/* we are not clearing here monologues not associated with us,
* only checking, if we can afford whole call destroy.
*/
if (g_hash_table_size(ml->associated_tags) > 0) {
ret |= 0x1;
break;
}
}
}
/* otherwise, we have only one call leg, so association monologue A to monologue B (no other branches)
* and we can simple destroy the whole call */
g_list_free(associated);
return ret;
}
@ -4377,6 +4352,19 @@ static void __tags_associate(struct call_monologue *a, struct call_monologue *b)
g_hash_table_insert(b->associated_tags, a, a);
}
/**
* Check whether the call object contains some other monologues, which can have own associations.
*/
static bool call_monologues_associations_left(struct call * c) {
for (GList * l = c->monologues.head; l; l = l->next)
{
struct call_monologue * ml = l->data;
if (g_hash_table_size(ml->associated_tags) > 0)
return true;
}
return false;
}
/**
* Based on given From-tag create a new monologue for this dialog,
* if given tag wasn't present in 'tags' of this call.
@ -4683,10 +4671,19 @@ do_delete:
monologue_stop(cs->monologue);
}
/* check, if we have some associated monologues left, which have own associations
* which means they need a media to flow */
unsigned int del_ret = monologue_delete_iter(ml, delete_delay);
/* if there are no associated dialogs, which still require media, then additionally
* ensure, whether we can afford to destroy the whole call now.
* Maybe some of them still need a media to flow */
bool del_stop = false;
del_stop = call_monologues_associations_left(c);
if ((del_ret & 0x2))
update = true;
if (!(del_ret & 0x1))
if (!(del_ret & 0x1) && !del_stop)
goto del_all;
goto success_unlock;

Loading…
Cancel
Save