diff options
author | Abdo-Gaber <abdo.gaber@ni.com> | 2019-03-25 15:30:36 +0100 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-04-11 16:46:05 -0700 |
commit | f4c64181e386e81829c90c9bd8d3cbc6cf37cee9 (patch) | |
tree | 80ba87cec483948ca2e42142c9648ecd2a58b7c5 | |
parent | 497513c74d79d75cf9a1bbe4eb0f441ef99f339e (diff) | |
download | uhd-f4c64181e386e81829c90c9bd8d3cbc6cf37cee9.tar.gz uhd-f4c64181e386e81829c90c9bd8d3cbc6cf37cee9.tar.bz2 uhd-f4c64181e386e81829c90c9bd8d3cbc6cf37cee9.zip |
log: fix deadlock issue on Windows machines
In log.cpp, a deadlock can occur while popping elements from the log
queue. If the queue is empty, the call does not timeout, and waits
infinitely. Replacing pop_with_wait() with pop_with_timed_wait() solves
this issue.
-rw-r--r-- | host/lib/utils/log.cpp | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/host/lib/utils/log.cpp b/host/lib/utils/log.cpp index f2f0e24ff..05f69319e 100644 --- a/host/lib/utils/log.cpp +++ b/host/lib/utils/log.cpp @@ -1,6 +1,7 @@ // // Copyright 2012,2014,2016 Ettus Research LLC // Copyright 2018 Ettus Research, a National Instruments Company +// Copyright 2019 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: GPL-3.0-or-later // @@ -20,7 +21,8 @@ #include <mutex> #include <thread> -namespace pt = boost::posix_time; +namespace pt = boost::posix_time; +constexpr double READ_TIMEOUT = 0.5; // Waiting time to read from the queue // Don't make these static const std::string -- we need their lifetime guaranteed! #define PURPLE "\033[35;1m" // purple @@ -233,6 +235,9 @@ public: ~log_resource(void) { _exit = true; + +#ifndef BOOST_MSVC // push a final message is required, since the pop_with_wait() function + // will be used. // We push a final message to kick the pop task out of it's wait state. // This wouldn't be necessary if pop_with_wait() could fail. Should // that ever get fixed, we can remove this. @@ -244,9 +249,11 @@ public: boost::this_thread::get_id()); final_message.message = ""; push(final_message); -#ifndef UHD_LOG_FASTPATH_DISABLE +# ifndef UHD_LOG_FASTPATH_DISABLE push_fastpath(""); -#endif +# endif +#endif // BOOST_MSVC + _pop_task->join(); { std::lock_guard<std::mutex> l(_logmap_mutex); @@ -296,8 +303,16 @@ public: // For the lifetime of this thread, we run the following loop: while (!_exit) { +#ifdef BOOST_MSVC + // Some versions of MSVC will hang if threads are being joined after main has + // completed, so we need to guarantee a timeout here + if (_log_queue.pop_with_timed_wait(log_info, READ_TIMEOUT)) { + _handle_log_info(log_info); + } +#else _log_queue.pop_with_wait(log_info); // Blocking call _handle_log_info(log_info); +#endif // BOOST_MSVC } // Exit procedure: Clear the queue @@ -313,8 +328,16 @@ public: #ifndef UHD_LOG_FASTPATH_DISABLE std::string msg; while (!_exit) { +# ifdef BOOST_MSVC + // Some versions of MSVC will hang if threads are being joined after main has + // completed, so we need to guarantee a timeout here + if (_fastpath_queue.pop_with_timed_wait(msg, READ_TIMEOUT)) { + std::cerr << msg << std::flush; + } +# else _fastpath_queue.pop_with_wait(msg); std::cerr << msg << std::flush; +# endif // BOOST_MSVC } // Exit procedure: Clear the queue @@ -329,7 +352,13 @@ public: #ifndef UHD_LOG_FASTPATH_DISABLE std::string msg; while (!_exit) { +# ifdef BOOST_MSVC + // Some versions of MSVC will hang if threads are being joined after main has + // completed, so we need to guarantee a timeout here + _fastpath_queue.pop_with_timed_wait(msg, READ_TIMEOUT); +# else _fastpath_queue.pop_with_wait(msg); +# endif // BOOST_MSVC } // Exit procedure: Clear the queue |