watcher: Avoid logging on level 1 while holding the mutex

This could be problematic in case loggers in some way rely on watcher_t
themselves.  This particular log message should rarely occur if at all,
but still avoid holding the mutex.
This commit is contained in:
Tobias Brunner
2023-04-27 13:45:32 +02:00
parent 2cb6d144a6
commit 7c657e78ff
2 changed files with 23 additions and 13 deletions
+21 -11
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016 Tobias Brunner * Copyright (C) 2016-2023 Tobias Brunner
* Copyright (C) 2013 Martin Willi * Copyright (C) 2013 Martin Willi
* *
* Copyright (C) secunet Security Networks AG * Copyright (C) secunet Security Networks AG
@@ -168,20 +168,27 @@ typedef struct {
} notify_data_t; } notify_data_t;
/** /**
* Notify watcher thread about changes * Notify watcher thread about changes and unlock mutex
*/ */
static void update(private_watcher_t *this) static void update_and_unlock(private_watcher_t *this)
{ {
char buf[1] = { 'u' }; char buf[1] = { 'u' };
int error = 0;
this->pending = TRUE; this->pending = TRUE;
if (this->notify[1] != -1) if (this->notify[1] != -1)
{ {
if (write(this->notify[1], buf, sizeof(buf)) == -1) if (write(this->notify[1], buf, sizeof(buf)) == -1)
{ {
DBG1(DBG_JOB, "notifying watcher failed: %s", strerror(errno)); error = errno;
} }
} }
this->mutex->unlock(this->mutex);
if (error)
{
DBG1(DBG_JOB, "notifying watcher failed: %s", strerror(error));
}
} }
/** /**
@@ -233,9 +240,8 @@ static void notify_end(notify_data_t *data)
break; break;
} }
} }
update(this);
this->condvar->broadcast(this->condvar); this->condvar->broadcast(this->condvar);
this->mutex->unlock(this->mutex); update_and_unlock(this);
free(data); free(data);
} }
@@ -258,7 +264,7 @@ static void notify(private_watcher_t *this, entry_t *entry,
.this = this, .this = this,
); );
/* deactivate entry, so we can select() other FDs even if the async /* deactivate entry, so we can poll() other FDs even if the async
* processing did not handle the event yet */ * processing did not handle the event yet */
entry->in_callback++; entry->in_callback++;
@@ -497,15 +503,16 @@ METHOD(watcher_t, add, void,
if (this->state == WATCHER_STOPPED) if (this->state == WATCHER_STOPPED)
{ {
this->state = WATCHER_QUEUED; this->state = WATCHER_QUEUED;
this->mutex->unlock(this->mutex);
lib->processor->queue_job(lib->processor, lib->processor->queue_job(lib->processor,
(job_t*)callback_job_create_with_prio((void*)watch, this, (job_t*)callback_job_create_with_prio((void*)watch, this,
NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
} }
else else
{ {
update(this); update_and_unlock(this);
} }
this->mutex->unlock(this->mutex);
} }
METHOD(watcher_t, remove_, void, METHOD(watcher_t, remove_, void,
@@ -544,9 +551,12 @@ METHOD(watcher_t, remove_, void,
} }
if (found) if (found)
{ {
update(this); update_and_unlock(this);
}
else
{
this->mutex->unlock(this->mutex);
} }
this->mutex->unlock(this->mutex);
} }
METHOD(watcher_t, get_state, watcher_state_t, METHOD(watcher_t, get_state, watcher_state_t,
+2 -2
View File
@@ -38,7 +38,7 @@ typedef enum watcher_state_t watcher_state_t;
* re-enable the event, while the data read can be processed in another * re-enable the event, while the data read can be processed in another
* asynchronous job. * asynchronous job.
* *
* On Linux, even if select() marks an FD as "ready", a subsequent read/write * On Linux, even if poll() marks an FD as "ready", a subsequent read/write
* can block. It is therefore highly recommended to use non-blocking I/O * can block. It is therefore highly recommended to use non-blocking I/O
* and handle EAGAIN/EWOULDBLOCK gracefully. * and handle EAGAIN/EWOULDBLOCK gracefully.
* *
@@ -71,7 +71,7 @@ enum watcher_state_t {
}; };
/** /**
* Watch multiple file descriptors using select(). * Watch multiple file descriptors using poll().
*/ */
struct watcher_t { struct watcher_t {