This is an automated email from the ASF dual-hosted git repository. jerpelea pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit 2d949fa7c57b1a836f1217d8093787a63c9c04a1 Author: Nightt <[email protected]> AuthorDate: Mon May 25 10:46:59 2026 +0800 system/settings: Avoid recursive save locking Fix #3105 by making the immediate save path write pending settings while the caller still owns g_settings.mtx instead of calling the timer callback, which locks the same mutex again. The cached-save timer callback still takes the mutex before using the same locked helper, so asynchronous saves keep their existing synchronization while non-cached saves no longer depend on a recursive mutex. Signed-off-by: Nightt <[email protected]> --- system/settings/settings.c | 62 +++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/system/settings/settings.c b/system/settings/settings.c index 105c093dd..c478e96f8 100644 --- a/system/settings/settings.c +++ b/system/settings/settings.c @@ -82,7 +82,10 @@ static int set_ip(FAR setting_t *setting, FAR struct in_addr *ip); static int load(void); static void save(void); static void signotify(void); +static void dump_cache_locked(FAR bool *wrpend); +#ifdef CONFIG_SYSTEM_SETTINGS_CACHED_SAVES static void dump_cache(union sigval ptr); +#endif /**************************************************************************** * Private Data @@ -623,12 +626,7 @@ static void save(void) #ifdef CONFIG_SYSTEM_SETTINGS_CACHED_SAVES timer_settime(g_settings.timerid, 0, &g_settings.trigger, NULL); #else - union sigval value = - { - .sival_ptr = &g_settings.wrpend, - }; - - dump_cache(value); + dump_cache_locked(&g_settings.wrpend); #endif } @@ -662,51 +660,63 @@ static void signotify(void) } /**************************************************************************** - * Name: dump_cache + * Name: dump_cache_locked * * Description: - * Writes out the cached data to the appropriate storage + * Writes out the cached data to the appropriate storage. The caller + * must hold g_settings.mtx. * * Input Parameters: - * value - parameter passed if called from a timer signal + * wrpend - pending write flag to clear after dumping * * Returned Value: * None * ****************************************************************************/ -static void dump_cache(union sigval ptr) +static void dump_cache_locked(FAR bool *wrpend) { - int ret = OK; - FAR bool *wrpend = (bool *)ptr.sival_ptr; - int i; - ret = pthread_mutex_lock(&g_settings.mtx); - assert(ret >= 0); - for (i = 0; i < CONFIG_SYSTEM_SETTINGS_MAX_STORAGES; i++) { if ((g_settings.store[i].file[0] != '\0') && g_settings.store[i].save_fn) { - ret = g_settings.store[i].save_fn(g_settings.store[i].file); -#if 0 - if (ret < 0) - { - /* What to do? We can't return anything from a void function. - * - * MIGHT BE A FUTURE REVISIT NEEDED - */ - } -#endif + (void)g_settings.store[i].save_fn(g_settings.store[i].file); } } *wrpend = false; +} +#ifdef CONFIG_SYSTEM_SETTINGS_CACHED_SAVES +/**************************************************************************** + * Name: dump_cache + * + * Description: + * Writes out the cached data to the appropriate storage + * + * Input Parameters: + * value - parameter passed if called from a timer signal + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void dump_cache(union sigval ptr) +{ + FAR bool *wrpend = (FAR bool *)ptr.sival_ptr; + int ret; + + ret = pthread_mutex_lock(&g_settings.mtx); + assert(ret >= 0); + + dump_cache_locked(wrpend); pthread_mutex_unlock(&g_settings.mtx); } +#endif /**************************************************************************** * Name: sanity_check
