fw/services/normal/comm_session: improve mutex handling and file operations

Preventing two threads from accessing app_comm at the same time, which caused
an assert in certain cases

Signed-off-by: Joshua Jun <joshuajun@proton.me>
This commit is contained in:
Joshua Jun 2025-10-14 13:25:42 +02:00 committed by Jinchang
parent 4051c5bb97
commit 14f8d20467
1 changed files with 35 additions and 22 deletions

View File

@ -18,27 +18,47 @@
#include "process_management/app_manager.h" #include "process_management/app_manager.h"
#include "services/common/comm_session/app_session_capabilities.h" #include "services/common/comm_session/app_session_capabilities.h"
#include "services/normal/settings/settings_file.h" #include "services/normal/settings/settings_file.h"
#include "os/mutex.h"
#include "system/logging.h"
#include "system/passert.h"
#include "util/units.h" #include "util/units.h"
#define APP_SESSION_CAPABILITIES_CACHE_FILENAME "app_comm" #define APP_SESSION_CAPABILITIES_CACHE_FILENAME "app_comm"
#define APP_SESSION_CAPABILITIES_CACHE_FILE_MAX_USED_SPACE (KiBYTES(2)) #define APP_SESSION_CAPABILITIES_CACHE_FILE_MAX_USED_SPACE (KiBYTES(2))
static PebbleMutex *s_mutex;
static status_t prv_open(SettingsFile *settings_file) { static status_t prv_open(SettingsFile *settings_file) {
return settings_file_open(settings_file, APP_SESSION_CAPABILITIES_CACHE_FILENAME, return settings_file_open(settings_file, APP_SESSION_CAPABILITIES_CACHE_FILENAME,
APP_SESSION_CAPABILITIES_CACHE_FILE_MAX_USED_SPACE); APP_SESSION_CAPABILITIES_CACHE_FILE_MAX_USED_SPACE);
} }
static status_t prv_open_locked(SettingsFile *settings_file) {
mutex_lock(s_mutex);
status_t status = prv_open(settings_file);
if (FAILED(status)) {
mutex_unlock(s_mutex);
}
return status;
}
static void prv_close_and_unlock(SettingsFile *settings_file) {
settings_file_close(settings_file);
mutex_unlock(s_mutex);
}
bool comm_session_current_app_session_cache_has_capability(CommSessionCapability capability) { bool comm_session_current_app_session_cache_has_capability(CommSessionCapability capability) {
CommSession *app_session = comm_session_get_current_app_session(); CommSession *app_session = comm_session_get_current_app_session();
const Uuid app_uuid = app_manager_get_current_app_md()->uuid; const Uuid app_uuid = app_manager_get_current_app_md()->uuid;
SettingsFile settings_file; SettingsFile settings_file;
status_t open_status = prv_open(&settings_file); status_t open_status = prv_open_locked(&settings_file);
bool file_open = PASSED(open_status);
uint64_t cached_capabilities = 0; uint64_t cached_capabilities = 0;
if (PASSED(open_status)) { if (file_open) {
settings_file_get(&settings_file, settings_file_get(&settings_file,
&app_uuid, sizeof(app_uuid), &app_uuid, sizeof(app_uuid),
&cached_capabilities, sizeof(cached_capabilities)); &cached_capabilities, sizeof(cached_capabilities));
@ -49,28 +69,17 @@ bool comm_session_current_app_session_cache_has_capability(CommSessionCapability
// Connected, grab fresh capabilities data: // Connected, grab fresh capabilities data:
new_capabilities = comm_session_get_capabilities(app_session); new_capabilities = comm_session_get_capabilities(app_session);
if (FAILED(open_status)) { if (file_open && (new_capabilities != cached_capabilities)) {
// File open failed, return live data without saving to cache
goto done;
}
if (new_capabilities != cached_capabilities) {
settings_file_set(&settings_file, settings_file_set(&settings_file,
&app_uuid, sizeof(app_uuid), &app_uuid, sizeof(app_uuid),
&new_capabilities, sizeof(new_capabilities)); &new_capabilities, sizeof(new_capabilities));
} }
} else {
// Not connected, use cached data.
if (FAILED(open_status)) {
// File open failed, no cache available
goto done;
}
} }
settings_file_close(&settings_file);
done: if (file_open) {
prv_close_and_unlock(&settings_file);
}
return ((new_capabilities & capability) != 0); return ((new_capabilities & capability) != 0);
} }
@ -90,16 +99,20 @@ static void prv_rewrite_cb(SettingsFile *old_file,
void comm_session_app_session_capabilities_evict(const Uuid *app_uuid) { void comm_session_app_session_capabilities_evict(const Uuid *app_uuid) {
SettingsFile settings_file; SettingsFile settings_file;
if (PASSED(prv_open(&settings_file))) { if (PASSED(prv_open_locked(&settings_file))) {
settings_file_delete(&settings_file, app_uuid, sizeof(*app_uuid)); settings_file_delete(&settings_file, app_uuid, sizeof(*app_uuid));
settings_file_close(&settings_file); prv_close_and_unlock(&settings_file);
} }
} }
void comm_session_app_session_capabilities_init(void) { void comm_session_app_session_capabilities_init(void) {
s_mutex = mutex_create();
PBL_ASSERTN(s_mutex != NULL);
SettingsFile settings_file; SettingsFile settings_file;
if (PASSED(prv_open(&settings_file))) { if (PASSED(prv_open_locked(&settings_file))) {
settings_file_rewrite(&settings_file, prv_rewrite_cb, NULL); settings_file_rewrite(&settings_file, prv_rewrite_cb, NULL);
settings_file_close(&settings_file); prv_close_and_unlock(&settings_file);
} }
} }