From ec86cd7b2c2da7bd2fb732288e7064d059252571 Mon Sep 17 00:00:00 2001 From: Roman Pope Date: Wed, 23 Sep 2026 19:47:00 -0400 Subject: [PATCH] lib: Fix lost wakeup in msg_task startup msg_task_impl's constructor waits on _start_cv until _running is set, checking the predicate under _mutex. task_loop() set _running and called notify_one() without taking _mutex, so a notification sent after the constructor had checked the predicate but before it started to wait was lost, and the constructor then blocked forever. The condition-variable handshake replaced a boost::barrier, which cannot lose a wakeup, in 3855516f6f ("lib: Remove boost::thread usage from USB transports"), so UHD 4.10.0.0 and 4.11.0.0 are affected. On a B210 the hang leaves b200_impl's constructor blocked in msg_task::make() right after "Operating over USB 3.". It shows up most when the device is opened at a real-time priority, as SDR applications that raise their priority before opening the device do. Set _running while holding _mutex, then notify. --- host/lib/utils/tasks.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/host/lib/utils/tasks.cpp b/host/lib/utils/tasks.cpp index 67fccbcc5..8e4751394 100644 --- a/host/lib/utils/tasks.cpp +++ b/host/lib/utils/tasks.cpp @@ -124,7 +124,12 @@ public: private: void task_loop(const task_fcn_type& task_fcn) { - _running = true; + { + // Set the predicate under the mutex: the constructor checks it under + // _mutex before waiting, so a notify sent in between would be lost. + std::lock_guard lock(_mutex); + _running = true; + } _start_cv.notify_one(); try {