diff --git a/CMakeLists.txt b/CMakeLists.txt index b9f2f14..aff50df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,11 @@ project(ipctool C) set(CMAKE_C_STANDARD 99) set(CMAKE_C_FLAGS "-std=gnu99") +# sensors.c serialises sensor detection with a pthread mutex. On musl and +# glibc >= 2.34 the pthread symbols live in libc, but older glibc and uClibc +# need the explicit link flag, so ask for it rather than rely on the toolchain. +find_package(Threads REQUIRED) + cmake_policy(SET CMP0069 NEW) if(NOT BUILD_SHARED_LIBS) @@ -181,13 +186,15 @@ set(CYAML_TEST_SRC add_library(ipchw STATIC ${COMMON_LIB_SRC}) target_compile_definitions(ipchw PUBLIC STANDALONE_LIBRARY ${IPCHW_VENDOR_DEFS}) -target_link_libraries(ipchw m) +# Threads is carried on the interface so anything linking this static library +# (ipcinfo here, and external consumers of libipchw) pulls pthread in too. +target_link_libraries(ipchw m Threads::Threads) if(NOT ONLY_LIBRARY) add_executable(ipctool ${IPCTOOL_SRC} ${COMMON_LIB_SRC_ALL}) target_compile_definitions(ipctool PRIVATE ${IPCHW_ALL_VENDOR_DEFS}) - target_link_libraries(ipctool m) + target_link_libraries(ipctool m Threads::Threads) install(TARGETS ipctool RUNTIME DESTINATION /usr/bin/) add_executable(ipcinfo example/ipcinfo.c src/tools.c ${VERSION_SRC}) diff --git a/src/sensors.c b/src/sensors.c index 4e96ddd..f4b94ee 100644 --- a/src/sensors.c +++ b/src/sensors.c @@ -1233,10 +1233,13 @@ if (!open_i2c_sensor_fd(i2c_adapter_nr)) } - -} +} + /* All buses probed, nothing answered. Without this the function fell off + * the end (UB): the bool came back indeterminate — often true — and the + * caller then formatted an uninitialised ctx into a garbage name. */ + return false; } #ifndef STANDALONE_LIBRARY @@ -1275,20 +1278,36 @@ cJSON *detect_sensors() { #endif +/* getsensorid() drives i2c detection through the process-global i2c_adapter_nr + * and both entry points below format into one shared sensor_indentity buffer, + * none of it locked. Two threads calling these at once stomp the adapter number + * mid-probe (wrong bus -> detection fails -> garbage) and tear the buffer write. + * Serialise the whole detect-and-format so every returned value is one complete, + * valid string. */ +static pthread_mutex_t sensor_indentity_mtx = PTHREAD_MUTEX_INITIALIZER; static char sensor_indentity[16]; const char *getsensoridentity() { + pthread_mutex_lock(&sensor_indentity_mtx); sensor_ctx_t ctx; - if (!getsensorid(&ctx)) - return NULL; - lsnprintf(sensor_indentity, sizeof(sensor_indentity), "%s_%s", - ctx.sensor_id, ctx.control); - return sensor_indentity; + const char *ret = NULL; + if (getsensorid(&ctx)) { + lsnprintf(sensor_indentity, sizeof(sensor_indentity), "%s_%s", + ctx.sensor_id, ctx.control); + ret = sensor_indentity; + } + pthread_mutex_unlock(&sensor_indentity_mtx); + return ret; } const char *getsensorshort() { + pthread_mutex_lock(&sensor_indentity_mtx); sensor_ctx_t ctx; - if (!getsensorid(&ctx)) - return NULL; - lsnprintf(sensor_indentity, sizeof(sensor_indentity), "%s", ctx.sensor_id); - return sensor_indentity; + const char *ret = NULL; + if (getsensorid(&ctx)) { + lsnprintf(sensor_indentity, sizeof(sensor_indentity), "%s", + ctx.sensor_id); + ret = sensor_indentity; + } + pthread_mutex_unlock(&sensor_indentity_mtx); + return ret; }