fix(parameters): initialize the recursive param mutex in param_init()

The param access mutex must be recursive because a layered param lookup
re-enters the lock on the same thread (Layer::get() -> _parent->get()).

Initialize it in param_init() - which runs once before any thread accesses
parameters - via pthread_mutexattr_settype(PTHREAD_MUTEX_RECURSIVE), replacing
the previous pthread_once lazy init. This avoids the non-portable glibc static
initializer PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, which is unavailable on QURT
and gated behind _GNU_SOURCE elsewhere (broke the voxl2 and SITL builds).
This commit is contained in:
Julian Oes
2026-06-24 13:30:35 +12:00
committed by Ramon Roche
parent 76742a4e98
commit 1ab4774e31
3 changed files with 21 additions and 3 deletions

View File

@@ -34,10 +34,18 @@
#include "atomic_transaction.h"
#ifdef __PX4_POSIX
// The mutex is recursive because a param lookup walks the layered param stack
// holding the lock and delegates to the parent layer (Layer::get() ->
// _parent->get()), which takes the same mutex again on the same thread.
//
// The recursive attribute is set at runtime rather than via a static initializer:
// PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP is a glibc extension that is not portable
// (unavailable on e.g. QURT, and gated behind _GNU_SOURCE elsewhere). initialize()
// is called from param_init(), before any thread accesses parameters, so there is
// no lazy-init race.
static pthread_mutex_t _param_mutex;
static pthread_once_t _param_mutex_once = PTHREAD_ONCE_INIT;
static void _init_param_mutex()
void AtomicTransaction::initialize()
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
@@ -48,7 +56,6 @@ static void _init_param_mutex()
pthread_mutex_t *AtomicTransaction::_get_mutex()
{
pthread_once(&_param_mutex_once, _init_param_mutex);
return &_param_mutex;
}
#endif

View File

@@ -54,6 +54,12 @@ private:
#endif
public:
#ifdef __PX4_POSIX
// Initialize the recursive param mutex. Must be called once before any thread
// accesses parameters (done from param_init()).
static void initialize();
#endif
AtomicTransaction()
{
lock();

View File

@@ -130,6 +130,11 @@ static pthread_mutex_t file_mutex =
void
param_init()
{
#ifdef __PX4_POSIX
// Set up the recursive param mutex before any thread can access parameters.
AtomicTransaction::initialize();
#endif
param_export_perf = perf_alloc(PC_ELAPSED, "param: export");
param_find_perf = perf_alloc(PC_COUNT, "param: find");
param_get_perf = perf_alloc(PC_COUNT, "param: get");