From 97c9e3648f43ff0ab1d81ae4af37ed3fefc10231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Wed, 4 Dec 2024 03:27:02 +0100 Subject: [PATCH] audio: fix reacting on mic enable/disable requests First of all, after getting an event of QubesDB FD, actually call qdb_read_watch() so the event is cleared and the next one can be received. But that's not enough. libqubesdb's queueing of watches doesn't handle well using the same connection for both watches and commands, and using non-blocking mode (monitoring qdb_watch_fd(), instead of calling qdb_read_watch() in a loop). While this issue wants fixing on the libqubesdb side, for now use separate connection to workaround the issue. Fixes QubesOS/qubes-issues#9619 --- pulse/pacat-simple-vchan.c | 27 +++++++++++++++++++++++---- pulse/pacat-simple-vchan.h | 1 + 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/pulse/pacat-simple-vchan.c b/pulse/pacat-simple-vchan.c index 1cc997da..da06e9a5 100644 --- a/pulse/pacat-simple-vchan.c +++ b/pulse/pacat-simple-vchan.c @@ -847,10 +847,19 @@ static void control_socket_callback(pa_mainloop_api *UNUSED(a), struct userdata *u = userdata; int new_rec_allowed = -1; + char *watch_path; if (!(f & PA_IO_EVENT_INPUT)) return; + watch_path = qdb_read_watch(u->watch_qdb); + if (!watch_path) { + pacat_log("Failed to read the qdb watch"); + return; + } + /* don't bother checking which watch fired, there is just one */ + free(watch_path); + new_rec_allowed = is_rec_allowed_from_qdb(u); if (new_rec_allowed >= 0) { g_mutex_lock(&u->prop_mutex); @@ -903,13 +912,20 @@ static int setup_control(struct userdata *u) { u->qdb_config_path = NULL; goto fail; } + // Setup a QubesDB watch to get authorization on demand - if (!qdb_watch(u->qdb, u->qdb_config_path)) { + u->watch_qdb = qdb_open(NULL); + if (!u->watch_qdb) { + pacat_log("qdb_open (watch) failed: %s", strerror(errno)); + goto fail; + } + + if (!qdb_watch(u->watch_qdb, u->qdb_config_path)) { pacat_log("failed to setup watch on %s: %m\n", u->qdb_config_path); goto fail; } - socket_fd = qdb_watch_fd(u->qdb); + socket_fd = qdb_watch_fd(u->watch_qdb); if (socket_fd < 0) goto fail; @@ -946,8 +962,9 @@ static int setup_control(struct userdata *u) { if (u->control_socket_event) u->mainloop_api->io_free(u->control_socket_event); u->control_socket_event = NULL; - if (socket_fd >= 0) - close(socket_fd); + if (u->watch_qdb) + qdb_close(u->watch_qdb); + u->watch_qdb = NULL; return 1; } @@ -964,6 +981,8 @@ static void control_cleanup(struct userdata *u) { free(u->qdb_status_path); if (u->qdb_request_path) free(u->qdb_request_path); + if (u->watch_qdb) + qdb_close(u->watch_qdb); if (u->qdb) qdb_close(u->qdb); } diff --git a/pulse/pacat-simple-vchan.h b/pulse/pacat-simple-vchan.h index f117eb88..07e26a2a 100644 --- a/pulse/pacat-simple-vchan.h +++ b/pulse/pacat-simple-vchan.h @@ -32,6 +32,7 @@ struct userdata { GMutex prop_mutex; qdb_handle_t qdb; + qdb_handle_t watch_qdb; // separate connection for watches char *qdb_config_path; char *qdb_status_path; char *qdb_request_path;