From 30cdf15ff5bedb372a0173db6cd494636bb001a0 Mon Sep 17 00:00:00 2001 From: Eric Katzfey Date: Thu, 11 Jun 2026 13:19:43 -0700 Subject: [PATCH] fix(posix): make pxh app map initialization thread-safe Pxh lazily initializes the builtin app map from client handler threads. Concurrent first commands can both enter init_app_map() and mutate the static std::map at the same time. Use pthread_once so the map is populated exactly once before process_line() or tab completion read it. --- platforms/posix/src/px4/common/px4_daemon/pxh.cpp | 12 +++++++++--- platforms/posix/src/px4/common/px4_daemon/pxh.h | 3 +++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/platforms/posix/src/px4/common/px4_daemon/pxh.cpp b/platforms/posix/src/px4/common/px4_daemon/pxh.cpp index 609356484f7..f2bc7ebf0df 100644 --- a/platforms/posix/src/px4/common/px4_daemon/pxh.cpp +++ b/platforms/posix/src/px4/common/px4_daemon/pxh.cpp @@ -56,6 +56,7 @@ namespace px4_daemon { apps_map_type Pxh::_apps = {}; +pthread_once_t Pxh::_apps_once = PTHREAD_ONCE_INIT; Pxh *Pxh::_instance = nullptr; Pxh::Pxh() @@ -72,15 +73,18 @@ Pxh::~Pxh() } } +void Pxh::_init_apps() +{ + init_app_map(_apps); +} + int Pxh::process_line(const std::string &line, bool silently_fail) { if (line.empty()) { return 0; } - if (_apps.empty()) { - init_app_map(_apps); - } + pthread_once(&_apps_once, Pxh::_init_apps); std::stringstream line_stream(line); std::string word; @@ -458,6 +462,8 @@ void Pxh::_move_cursor(int position) void Pxh::_tab_completion(std::string &mystr) { + pthread_once(&_apps_once, Pxh::_init_apps); + // parse line and get command std::stringstream line(mystr); std::string cmd; diff --git a/platforms/posix/src/px4/common/px4_daemon/pxh.h b/platforms/posix/src/px4/common/px4_daemon/pxh.h index 39009bed11c..6d88f52908b 100644 --- a/platforms/posix/src/px4/common/px4_daemon/pxh.h +++ b/platforms/posix/src/px4/common/px4_daemon/pxh.h @@ -45,6 +45,7 @@ #include #include #include +#include #include #include "history.h" @@ -90,6 +91,7 @@ private: void _setup_term(); static void _restore_term(); + static void _init_apps(); bool _should_exit{false}; bool _local_terminal{false}; @@ -97,6 +99,7 @@ private: struct termios _orig_term {}; static apps_map_type _apps; + static pthread_once_t _apps_once; static Pxh *_instance; };