diff --git a/.github/build.sh b/.github/build.sh index 1d2f1c50..b0b08cb8 100755 --- a/.github/build.sh +++ b/.github/build.sh @@ -233,3 +233,4 @@ cmake --build . --target test-aws-iot-device-client ### Run Tests ### env AWS_CRT_MEMORY_TRACING=1 ./test/test-aws-iot-device-client +./test/test-aws-iot-device-client --gtest_filter=LogQueueTest.notifyAllOnShutdown --gtest_repeat=1000 \ No newline at end of file diff --git a/source/logging/LogQueue.cpp b/source/logging/LogQueue.cpp index 307d73b6..4ed72fd3 100644 --- a/source/logging/LogQueue.cpp +++ b/source/logging/LogQueue.cpp @@ -2,10 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 #include "LogQueue.h" +#include +#include using namespace std; using namespace Aws::Iot::DeviceClient::Logging; +constexpr int LogQueue::EMPTY_WAIT_TIME_MILLISECONDS; + void LogQueue::addLog(unique_ptr log) { unique_lock addLock(queueLock); @@ -23,10 +27,12 @@ bool LogQueue::hasNextLog() std::unique_ptr LogQueue::getNextLog() { unique_lock readLock(queueLock); + while (logQueue.empty() && !isShutdown) { - newLogNotifier.wait(readLock); + newLogNotifier.wait_for(readLock, chrono::milliseconds(EMPTY_WAIT_TIME_MILLISECONDS)); } + if (logQueue.empty()) { return NULL; diff --git a/source/logging/LogQueue.h b/source/logging/LogQueue.h index 143adabb..27b51298 100644 --- a/source/logging/LogQueue.h +++ b/source/logging/LogQueue.h @@ -5,6 +5,7 @@ #define DEVICE_CLIENT_LOGQUEUE_H #include "LogMessage.h" +#include #include #include #include @@ -27,7 +28,12 @@ namespace Aws /** * \brief Whether the LogQueue has been shutdown or not. */ - bool isShutdown = false; + std::atomic isShutdown{false}; + /** + * \brief The default value in milliseconds for which Device client will wait after blocking when + * the queue is empty. + */ + static constexpr int EMPTY_WAIT_TIME_MILLISECONDS = 200; /** * \brief a Mutex used to control multi-threaded access to the LogQueue */ diff --git a/source/main.cpp b/source/main.cpp index 9930759d..0729321a 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -151,8 +151,7 @@ void shutdown() } /** - * \brief This function is a wrapper around abort() which makes sure we let the user know - * that we are aborting execution due to some type of configuration issue + * \brief This function shuts down device client when aborting execution due to some type of configuration issue * * @param reason the reason why the abort is happening */ @@ -160,11 +159,7 @@ void deviceClientAbort(string reason) { cout << "AWS IoT Device Client must abort execution, reason: " << reason << endl; cout << "Please check the AWS IoT Device Client logs for more information" << endl; - if (lockFile) - { - lockFile.reset(); - } - abort(); + exit(EXIT_FAILURE); } void handle_feature_stopped(Feature *feature) diff --git a/test/logging/TestLogQueue.cpp b/test/logging/TestLogQueue.cpp index eb4914ce..a7e46b59 100644 --- a/test/logging/TestLogQueue.cpp +++ b/test/logging/TestLogQueue.cpp @@ -85,8 +85,9 @@ TEST_F(LogQueueTest, notifyAllOnShutdown) logQueue->shutdown(); - cv.wait_for(lock1, chrono::seconds(1)); - cv2.wait_for(lock2, chrono::seconds(1)); + // 400ms is 2 * EMPTY_WAIT_TIME_MILLISECONDS as defined in LogQueue.h + cv.wait_for(lock1, chrono::milliseconds(400)); + cv2.wait_for(lock2, chrono::milliseconds(400)); ASSERT_TRUE(processed && processed2); }