watcher: Properly handle conflict during concurrent FD removal

If an FD we intend to remove is currently busy in a callback, we wait
on a condvar to retry later.  If the FD is not the first in the list,
`prev` will be set to the previous entry in the list.  This is fine
when no other threads are concurrently removing FDs, the same entry will
be found on the next try and prev points to the same value again.
However, if other threads also remove one or more FDs and the initial FD
is now the first in the list `prev` should be NULL and not point to a
removed entry.

Fixes: b27663399b ("watcher: Avoid allocations due to enumerators")
This commit is contained in:
Tobias Brunner
2026-07-24 08:47:37 +02:00
parent 3ec8d3cff1
commit 313d1ef88a
+1 -1
View File
@@ -561,12 +561,12 @@ METHOD(watcher_t, add, void,
METHOD(watcher_t, remove_, void,
private_watcher_t *this, int fd)
{
entry_t *entry, *prev = NULL;
watcher_event_t found = 0;
this->mutex->lock(this->mutex);
while (TRUE)
{
entry_t *entry, *prev = NULL;
bool is_in_callback = FALSE;
entry = this->fds;