Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.5:Update
strongswan
0055-vici-dont-lock-connection-in-write-mode-wh...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0055-vici-dont-lock-connection-in-write-mode-when-enabling-on_write-callback.patch of Package strongswan
commit 2cb6d144a6f3da6d1f006bf8252fa90a9514d435 Author: Tobias Brunner <tobias@strongswan.org> Date: Thu Apr 13 13:55:00 2023 +0200 vici: Don't lock connection in write mode when enabling on_write() callback This should prevent a deadlock that could previously be caused when a control-log event was raised. The deadlock looked something like this: * Thread A holds the read lock on bus_t and raises the control-log event. This requires acquiring the connection entry in write mode to queue the outgoing message. If it is already held by another thread, this blocks on a condvar. * Thread B is registering the on_write() callback on the same connection's stream due to a previous log message. Before this change, the code acquired the entry in write mode as well, thus, blocking thread A. To remove/add the stream, the mutex in watcher_t needs to be acquired. * Thread C is in watcher_t's watch() and holds the mutex while logging on level 2 or 3. The latter requires the read lock on bus_t, which should usually be acquirable even if thread A holds it. Unless writers are concurrently waiting on the lock and the implementation is blocking new readers to prevent writer starvation. * Thread D is removing a logger from the bus (e.g. after an initiate() call) and is waiting to acquire the write lock on bus_t and is thereby blocking thread C. With this change, thread B should not block thread A anymore. So thread D and thread C should eventually be able to proceed as well. Thread A could be held up a bit if there is a thread already sending messages for the same connection, but that should only cause a delay, no deadlock, as on_write() and do_write() don't log (or lock) anything while keeping the entry locked in write mode. Closes strongswan/strongswan#566 diff --git a/src/libcharon/plugins/vici/vici_socket.c b/src/libcharon/plugins/vici/vici_socket.c index 21bdead14..39d34e4d3 100644 --- a/src/libcharon/plugins/vici/vici_socket.c +++ b/src/libcharon/plugins/vici/vici_socket.c @@ -127,6 +127,8 @@ typedef struct { int readers; /** any users writing over this connection? */ int writers; + /** any users using this connection at all? */ + int users; /** condvar to wait for usage */ condvar_t *cond; } entry_t; @@ -211,6 +213,7 @@ static entry_t* find_entry(private_vici_socket_t *this, stream_t *stream, { entry->writers++; } + entry->users++; found = entry; break; } @@ -240,7 +243,7 @@ static entry_t* remove_entry(private_vici_socket_t *this, u_int id) if (entry->id == id) { candidate = TRUE; - if (entry->readers || entry->writers) + if (entry->readers || entry->writers || entry->users) { entry->cond->wait(entry->cond, this->mutex); break; @@ -273,6 +276,7 @@ static void put_entry(private_vici_socket_t *this, entry_t *entry, { entry->writers--; } + entry->users--; entry->cond->signal(entry->cond); this->mutex->unlock(this->mutex); } @@ -583,6 +587,7 @@ CALLBACK(on_accept, bool, .queue = array_create(sizeof(chunk_t), 0), .cond = condvar_create(CONDVAR_TYPE_DEFAULT), .readers = 1, + .users = 1, ); this->mutex->lock(this->mutex); @@ -606,11 +611,13 @@ CALLBACK(enable_writer, job_requeue_t, { entry_t *entry; - entry = find_entry(sel->this, NULL, sel->id, FALSE, TRUE); + /* we don't modify the in- or outbound queue, so don't lock the entry in + * reader or writer mode */ + entry = find_entry(sel->this, NULL, sel->id, FALSE, FALSE); if (entry) { entry->stream->on_write(entry->stream, on_write, sel->this); - put_entry(sel->this, entry, FALSE, TRUE); + put_entry(sel->this, entry, FALSE, FALSE); } return JOB_REQUEUE_NONE; }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor