From 83df30881907529df0be5e89883d8c8530ccf1da Mon Sep 17 00:00:00 2001 From: Simo Piiroinen Date: Mon, 1 Apr 2019 13:07:43 +0300 Subject: [PATCH] [worker] Use private copy of mode data. JB#45312 When a dynamic mode is activated from the worker thread, a pointer to shared mode data is cached. If mode data gets invalidated due to the main thread reloading configuration files, the worker thread will dereference a stale pointer during mode deactivation. Cache clone of mode data instead of just holding pointer to shared data. Note that this only fixes logical error in expected behavior during config reload, there is still race condition in mode data duplication stage. Signed-off-by: Simo Piiroinen --- src/usb_moded-network.c | 1 + src/usb_moded-worker.c | 9 +++++---- src/usb_moded-worker.h | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/usb_moded-network.c b/src/usb_moded-network.c index 68c34f7..2e8a588 100644 --- a/src/usb_moded-network.c +++ b/src/usb_moded-network.c @@ -1295,6 +1295,7 @@ int network_update(void) LOG_REGISTER_CONTEXT; if( control_get_cable_state() == CABLE_STATE_PC_CONNECTED ) { + // FIXME: data hazard const modedata_t *data = worker_get_usb_mode_data(); if( data && data->network ) { network_down(data); diff --git a/src/usb_moded-worker.c b/src/usb_moded-worker.c index a6cff3e..16b8946 100644 --- a/src/usb_moded-worker.c +++ b/src/usb_moded-worker.c @@ -69,7 +69,7 @@ static bool worker_set_requested_mode_locked(const char *mode); void worker_request_hardware_mode (const char *mode); void worker_clear_hardware_mode (void); static void worker_execute (void); -void worker_switch_to_mode (const char *mode); +static void worker_switch_to_mode (const char *mode); static guint worker_add_iowatch (int fd, bool close_on_unref, GIOCondition cnd, GIOFunc io_cb, gpointer aptr); static void *worker_thread_cb (void *aptr); static gboolean worker_notify_cb (GIOChannel *chn, GIOCondition cnd, gpointer data); @@ -391,7 +391,7 @@ void worker_clear_kernel_module(void) * ------------------------------------------------------------------------- */ /** Contains the mode data */ -static const modedata_t *worker_mode_data = NULL; +static modedata_t *worker_mode_data = NULL; /** get the usb mode data * @@ -414,7 +414,8 @@ void worker_set_usb_mode_data(const modedata_t *data) { LOG_REGISTER_CONTEXT; - worker_mode_data = data; + modedata_free(worker_mode_data), + worker_mode_data = modedata_copy(data); } /* ------------------------------------------------------------------------- * @@ -546,7 +547,7 @@ worker_execute(void) * MODE_SWITCH * ------------------------------------------------------------------------- */ -void +static void worker_switch_to_mode(const char *mode) { LOG_REGISTER_CONTEXT; diff --git a/src/usb_moded-worker.h b/src/usb_moded-worker.h index f4a47d2..99b5a2a 100644 --- a/src/usb_moded-worker.h +++ b/src/usb_moded-worker.h @@ -48,7 +48,6 @@ const modedata_t *worker_get_usb_mode_data (void); void worker_set_usb_mode_data (const modedata_t *data); void worker_request_hardware_mode(const char *mode); void worker_clear_hardware_mode (void); -void worker_switch_to_mode (const char *mode); bool worker_init (void); void worker_quit (void); void worker_wakeup (void); -- 2.23.0