From 6667aa071ecfac7418b49354b25c06a40ff4acfe Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Tue, 1 Aug 2017 13:35:58 -0700 Subject: C API: Make uhd_get_last_error() thread-safe The function was directly accessing the error message cache, bypassing locks, and thus could be faulty if being called the same time as another UHD component would update the error string. --- host/include/uhd/error.h | 3 ++- host/lib/error_c.cpp | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/host/include/uhd/error.h b/host/include/uhd/error.h index 77216dc72..5be04b7b4 100644 --- a/host/include/uhd/error.h +++ b/host/include/uhd/error.h @@ -87,7 +87,8 @@ typedef enum { UHD_API uhd_error error_from_uhd_exception(const uhd::exception* e); -UHD_API const std::string& get_c_global_error_string(); +//! Return a copy of the last error string. +UHD_API std::string get_c_global_error_string(); UHD_API void set_c_global_error_string(const std::string &msg); diff --git a/host/lib/error_c.cpp b/host/lib/error_c.cpp index 3ce63a81d..622d3ee34 100644 --- a/host/lib/error_c.cpp +++ b/host/lib/error_c.cpp @@ -45,11 +45,14 @@ uhd_error error_from_uhd_exception(const uhd::exception* e){ } // Store the error string in a single place in library +// Note: Don't call _c_global_error_string() directly, it needs to be locked +// for thread-safety. Use set_c_global_error_string() and +// get_c_global_error_string() instead. UHD_SINGLETON_FCN(std::string, _c_global_error_string) static boost::mutex _error_c_mutex; -const std::string& get_c_global_error_string(){ +std::string get_c_global_error_string(){ boost::mutex::scoped_lock lock(_error_c_mutex); return _c_global_error_string(); } @@ -66,8 +69,9 @@ uhd_error uhd_get_last_error( size_t strbuffer_len ){ try{ + auto error_str = get_c_global_error_string(); memset(error_out, '\0', strbuffer_len); - strncpy(error_out, _c_global_error_string().c_str(), strbuffer_len); + strncpy(error_out, error_str.c_str(), strbuffer_len); } catch(...){ return UHD_ERROR_UNKNOWN; -- cgit v1.2.3