mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-04 00:00:14 -04:00
ike-sa-manager: Avoid deadlock due to race condition during shutdown
If an entry is added while we wait for a checked out SA in flush() (e.g. due to an action performed by that SA), new entries might get inserted before the one we wait for. If that was the first entry in the row, we didn't correctly update the table and the new entries were basically lost by overwriting the first entry in the row. As the SA count was still increased but the new entries couldn't get enumerated, the daemon wasn't terminated properly but was stuck in the loop in flush().
This commit is contained in:
parent
3e0123526f
commit
d662a69d9d
@ -677,14 +677,15 @@ static void remove_entry(private_ike_sa_manager_t *this, entry_t *entry)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the entry at the current enumerator position.
|
||||
* Remove the entry at the current enumerator position. This only works for a
|
||||
* single concurrent thread.
|
||||
*/
|
||||
static void remove_entry_at(private_enumerator_t *this)
|
||||
{
|
||||
this->entry = NULL;
|
||||
if (this->current)
|
||||
{
|
||||
table_item_t *current = this->current;
|
||||
table_item_t *current = this->current, *prev;
|
||||
|
||||
ignore_result(ref_put(&this->manager->total_sa_count));
|
||||
this->current = this->prev;
|
||||
@ -694,8 +695,23 @@ static void remove_entry_at(private_enumerator_t *this)
|
||||
this->prev->next = current->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we started from the beginning of the row, but while we waited
|
||||
* for the entry in flush(), one or more entries might have been
|
||||
* added, start from the beginning again in either case */
|
||||
prev = this->manager->ike_sa_table[this->row];
|
||||
if (prev != current)
|
||||
{
|
||||
while (prev->next != current)
|
||||
{
|
||||
prev = prev->next;
|
||||
}
|
||||
prev->next = current->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->manager->ike_sa_table[this->row] = current->next;
|
||||
}
|
||||
unlock_single_segment(this->manager, this->segment);
|
||||
}
|
||||
free(current);
|
||||
|
Loading…
x
Reference in New Issue
Block a user