| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * This file is part of the Falcon Player (FPP) and is Copyright (C) | ||
| 3 | * 2013-2022 by the Falcon Player Developers. | ||
| 4 | * | ||
| 5 | * The Falcon Player (FPP) is free software, and is covered under | ||
| 6 | * multiple Open Source licenses. Please see the included 'LICENSES' | ||
| 7 | * file for descriptions of what files are covered by each license. | ||
| 8 | * | ||
| 9 | * This source file is covered under the LGPL v2.1 as described in the | ||
| 10 | * included LICENSE.LGPL file. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include "fpp-pch.h" | ||
| 14 | |||
| 15 | #include <algorithm> | ||
| 16 | #include <atomic> | ||
| 17 | #include <mutex> | ||
| 18 | #include <semaphore> | ||
| 19 | #include <set> | ||
| 20 | #include <shared_mutex> | ||
| 21 | #include <stdio.h> | ||
| 22 | #include <thread> | ||
| 23 | #include <utility> | ||
| 24 | |||
| 25 | #include "fpp-json.h" // Json::Value -- the serialization side of FPPWarning lives here | ||
| 26 | |||
| 27 | #include "Warnings.h" | ||
| 28 | #include "common.h" | ||
| 29 | #include "log.h" | ||
| 30 | #include "settings.h" | ||
| 31 | |||
| 32 | using namespace std::chrono; | ||
| 33 | |||
| 34 | namespace | ||
| 35 | { | ||
| 36 | std::list<FPPWarning> warnings; | ||
| 37 | std::shared_mutex warningsLock; | ||
| 38 | std::mutex listenerListLock; | ||
| 39 | std::set<WarningListener*> listenerList; | ||
| 40 | steady_clock::time_point wakeUpTime = steady_clock::time_point::max(); | ||
| 41 | std::atomic_bool runNotifyThread{ false }; | ||
| 42 | // Intentionally leaked: if this were a plain static, __cxa_finalize would | ||
| 43 | // run ~thread() on ANY exit() call (early startup failures call exit(1) | ||
| 44 | // long before the orderly _exit(0) at the end of main()), and destroying | ||
| 45 | // a still-joinable std::thread calls std::terminate. Leaking the object | ||
| 46 | // means the destructor never runs; StopNotifyThread still joins it on the | ||
| 47 | // orderly shutdown path. | ||
| 48 | std::thread& notifyThread = *new std::thread(); | ||
| 49 | std::binary_semaphore sema{ 0 }; | ||
| 50 | } | ||
| 51 | |||
| 52 | static void PruneWarnings(); | ||
| 53 | |||
| 54 | 1633 | FPPWarning::FPPWarning(int i, const std::string& m, const std::string& p) : | |
| 55 | 1633 | m_id(i), | |
| 56 |
1/2✓ Branch 0 taken 1633 times.
✗ Branch 1 not taken.
|
1633 | m_message(m), |
| 57 |
1/2✓ Branch 0 taken 1633 times.
✗ Branch 1 not taken.
|
3266 | m_plugin(p) { |
| 58 | 1633 | timeout = steady_clock::time_point::max(); | |
| 59 | 1633 | } | |
| 60 | |||
| 61 | 25778 | Json::Value FPPWarning::toJsonValue() const { | |
| 62 | 25778 | Json::Value v; | |
| 63 |
2/4✓ Branch 0 taken 25778 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25778 times.
✗ Branch 3 not taken.
|
25778 | v["id"] = m_id; |
| 64 |
2/4✓ Branch 0 taken 25778 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25778 times.
✗ Branch 3 not taken.
|
25778 | v["message"] = m_message; |
| 65 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25778 times.
|
25778 | if (!m_plugin.empty()) { |
| 66 | ✗ | v["plugin"] = m_plugin; | |
| 67 | } | ||
| 68 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 25778 times.
|
25850 | for (auto& kv : data) { |
| 69 |
3/6✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
|
72 | v["data"][kv.first] = kv.second; |
| 70 | } | ||
| 71 | 25778 | return v; | |
| 72 | ✗ | } | |
| 73 | |||
| 74 | 3770 | void WarningHolder::AddWarningListener(WarningListener* l) { | |
| 75 |
1/2✓ Branch 0 taken 3770 times.
✗ Branch 1 not taken.
|
3770 | LogDebug(VB_GENERAL, "About to add listener\n"); |
| 76 |
1/2✓ Branch 0 taken 3770 times.
✗ Branch 1 not taken.
|
3770 | std::unique_lock<std::mutex> lock(listenerListLock); |
| 77 |
1/2✓ Branch 0 taken 3770 times.
✗ Branch 1 not taken.
|
3770 | listenerList.insert(l); |
| 78 |
1/2✓ Branch 0 taken 3770 times.
✗ Branch 1 not taken.
|
3770 | LogDebug(VB_GENERAL, "Adding Listener Done\n"); |
| 79 | 3770 | } | |
| 80 | |||
| 81 | 3734 | void WarningHolder::RemoveWarningListener(WarningListener* l) { | |
| 82 |
1/2✓ Branch 0 taken 3734 times.
✗ Branch 1 not taken.
|
3734 | std::unique_lock<std::mutex> lock(listenerListLock); |
| 83 |
2/4✓ Branch 0 taken 3734 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3734 times.
✗ Branch 3 not taken.
|
3734 | if (listenerList.erase(l)) { |
| 84 |
1/2✓ Branch 0 taken 3734 times.
✗ Branch 1 not taken.
|
3734 | LogDebug(VB_GENERAL, "Removing Warning Listener Complete\n"); |
| 85 | } else { | ||
| 86 | ✗ | LogWarn(VB_GENERAL, "Requested to remove Listener, but it wasn't found\n"); | |
| 87 | } | ||
| 88 | 3734 | } | |
| 89 | |||
| 90 | 1888 | void WarningHolder::StartNotifyThread() { | |
| 91 | 1888 | runNotifyThread = true; | |
| 92 |
1/2✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
|
1888 | notifyThread = std::thread(WarningHolder::WarningsThreadMain); |
| 93 | 1888 | } | |
| 94 | |||
| 95 | 1884 | void WarningHolder::StopNotifyThread() { | |
| 96 | 1884 | runNotifyThread = false; | |
| 97 | 1884 | sema.release(); | |
| 98 | // Guard the join: StopNotifyThread() can run when the thread was never | ||
| 99 | // started (a crash signal arrives before StartNotifyThread) or has already | ||
| 100 | // been joined (normal shutdown joins it, then a later crash re-enters the | ||
| 101 | // signal handler). join() on a non-joinable thread throws std::system_error | ||
| 102 | // on both Linux and macOS -> terminate. joinable() makes it safe/idempotent. | ||
| 103 | // Nor from the notify thread itself (a crash inside a warnings listener | ||
| 104 | // reaches here on that thread): joining yourself throws, which would | ||
| 105 | // terminate from inside the crash handler. | ||
| 106 |
5/6✓ Branch 0 taken 1884 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1883 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1883 times.
✓ Branch 5 taken 1 times.
|
1884 | if (notifyThread.joinable() && notifyThread.get_id() != std::this_thread::get_id()) { |
| 107 | 1883 | notifyThread.join(); | |
| 108 | } | ||
| 109 | 1884 | } | |
| 110 | 4414 | void WarningHolder::WriteWarningsFile() { | |
| 111 |
1/2✓ Branch 0 taken 4414 times.
✗ Branch 1 not taken.
|
4414 | Json::Value result = Json::Value(Json::ValueType::arrayValue); |
| 112 |
1/2✓ Branch 0 taken 4414 times.
✗ Branch 1 not taken.
|
4414 | Json::Value resultFull = Json::Value(Json::ValueType::arrayValue); |
| 113 | { | ||
| 114 | // Only the copy is made under the lock. The writes below are file | ||
| 115 | // I/O on the SD card, and every AddWarning/RemoveWarning -- some on | ||
| 116 | // the output and media timing paths -- waits for this lock. | ||
| 117 |
1/2✓ Branch 0 taken 4414 times.
✗ Branch 1 not taken.
|
4414 | std::shared_lock<std::shared_mutex> lock(warningsLock); |
| 118 |
2/2✓ Branch 0 taken 4854 times.
✓ Branch 1 taken 4414 times.
|
9268 | for (auto& warn : warnings) { |
| 119 |
2/4✓ Branch 0 taken 4854 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4854 times.
✗ Branch 3 not taken.
|
4854 | result.append(warn.message()); |
| 120 |
2/4✓ Branch 0 taken 4854 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4854 times.
✗ Branch 3 not taken.
|
4854 | resultFull.append(warn.toJsonValue()); |
| 121 | } | ||
| 122 | 4414 | } | |
| 123 |
4/8✓ Branch 0 taken 4414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4414 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4414 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4414 times.
✗ Branch 7 not taken.
|
17656 | SaveJsonToFile(result, getFPPDDir("/www/warnings.json")); |
| 124 |
4/8✓ Branch 0 taken 4414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4414 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4414 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4414 times.
✗ Branch 7 not taken.
|
13242 | SaveJsonToFile(resultFull, getFPPDDir("/www/warnings_full.json")); |
| 125 | 4414 | } | |
| 126 | 17 | void WarningHolder::WriteCrashedWarningsFile(int id, const std::string& message) { | |
| 127 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
|
17 | FPPWarning warn(id, message, ""); |
| 128 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | Json::Value result = Json::Value(Json::ValueType::arrayValue); |
| 129 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | Json::Value resultFull = Json::Value(Json::ValueType::arrayValue); |
| 130 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
|
17 | result.append(warn.message()); |
| 131 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
|
17 | resultFull.append(warn.toJsonValue()); |
| 132 |
4/8✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
|
68 | SaveJsonToFile(result, getFPPDDir("/www/warnings.json")); |
| 133 |
4/8✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
|
51 | SaveJsonToFile(resultFull, getFPPDDir("/www/warnings_full.json")); |
| 134 | 17 | } | |
| 135 | 1867 | void WarningHolder::ClearWarningsFile() { | |
| 136 |
2/4✓ Branch 0 taken 1867 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1867 times.
✗ Branch 3 not taken.
|
3734 | remove(getFPPDDir("/www/warnings.json").c_str()); |
| 137 |
2/4✓ Branch 0 taken 1867 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1867 times.
✗ Branch 3 not taken.
|
1867 | remove(getFPPDDir("/www/warnings_full.json").c_str()); |
| 138 | 1867 | } | |
| 139 | |||
| 140 | 1888 | void WarningHolder::WarningsThreadMain() { | |
| 141 |
2/4✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
✗ Branch 3 not taken.
|
1888 | SetThreadName("FPP-Warnings"); |
| 142 | 1888 | PruneWarnings(); | |
| 143 | 1888 | WriteWarningsFile(); | |
| 144 |
2/2✓ Branch 0 taken 4409 times.
✓ Branch 1 taken 2 times.
|
4411 | while (runNotifyThread) { |
| 145 | // Read under warningsLock, which every writer of wakeUpTime holds. | ||
| 146 | 4409 | steady_clock::time_point wake; | |
| 147 | { | ||
| 148 |
1/2✓ Branch 0 taken 4409 times.
✗ Branch 1 not taken.
|
4409 | std::shared_lock<std::shared_mutex> lock(warningsLock); |
| 149 | 4409 | wake = wakeUpTime; | |
| 150 | 4409 | } | |
| 151 | 4409 | sema.try_acquire_until(wake); | |
| 152 |
2/2✓ Branch 0 taken 1881 times.
✓ Branch 1 taken 2523 times.
|
4404 | if (!runNotifyThread) { |
| 153 | 1881 | break; | |
| 154 | } | ||
| 155 |
1/2✓ Branch 0 taken 2523 times.
✗ Branch 1 not taken.
|
2523 | PruneWarnings(); |
| 156 |
1/2✓ Branch 0 taken 2523 times.
✗ Branch 1 not taken.
|
2523 | WriteWarningsFile(); |
| 157 | |||
| 158 |
1/2✓ Branch 0 taken 2523 times.
✗ Branch 1 not taken.
|
2523 | auto copy = GetWarnings(); |
| 159 | |||
| 160 |
1/2✓ Branch 0 taken 2523 times.
✗ Branch 1 not taken.
|
2523 | LogDebug(VB_GENERAL, "Warnings may have changed; notifying other threads of %zu Warnings\n", copy.size()); |
| 161 | |||
| 162 |
1/2✓ Branch 0 taken 2523 times.
✗ Branch 1 not taken.
|
2523 | std::unique_lock lock(listenerListLock); |
| 163 |
1/2✓ Branch 0 taken 2523 times.
✗ Branch 1 not taken.
|
7023 | std::for_each(listenerList.begin(), listenerList.end(), [&](WarningListener* l) { l->handleWarnings(copy); }); |
| 164 | 2523 | } | |
| 165 | 1883 | } | |
| 166 | |||
| 167 | 30 | void WarningHolder::AddWarning(const std::string& w) { | |
| 168 |
2/4✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
|
30 | AddWarningTimeout(-1, UNKNOWN_WARNING_ID, w); |
| 169 | 30 | } | |
| 170 | 9 | void WarningHolder::AddWarningTimeout(const std::string& w, int seconds) { | |
| 171 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | AddWarningTimeout(seconds, UNKNOWN_WARNING_ID, w); |
| 172 | 9 | } | |
| 173 | ✗ | void WarningHolder::RemoveWarning(const std::string& w) { | |
| 174 | ✗ | RemoveWarning(UNKNOWN_WARNING_ID, w); | |
| 175 | ✗ | } | |
| 176 | 1039 | void WarningHolder::AddWarning(int id, const std::string& w, const std::map<std::string, std::string>& data) { | |
| 177 |
2/4✓ Branch 0 taken 1039 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1039 times.
✗ Branch 3 not taken.
|
1039 | AddWarningTimeout(-1, id, w, data); |
| 178 | 1039 | } | |
| 179 | 3 | void WarningHolder::AddWarning(int id, const std::string& w, const std::string& fixUrl, const std::string& fixText) { | |
| 180 | 3 | std::map<std::string, std::string> data; | |
| 181 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!fixUrl.empty()) { |
| 182 |
3/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
6 | data["fixUrl"] = fixUrl; |
| 183 | } | ||
| 184 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!fixText.empty()) { |
| 185 |
3/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
6 | data["fixText"] = fixText; |
| 186 | } | ||
| 187 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | AddWarningTimeout(-1, id, w, data); |
| 188 | 3 | } | |
| 189 | |||
| 190 | 2600 | void WarningHolder::AddWarningTimeout(int sec, int id, const std::string& w, const std::map<std::string, std::string>& data, const std::string& plugin) { | |
| 191 |
1/2✓ Branch 0 taken 2600 times.
✗ Branch 1 not taken.
|
2600 | LogDebug(VB_GENERAL, "Adding Warning: %s\n", w.c_str()); |
| 192 | 2600 | steady_clock::time_point timeoutTime = steady_clock::time_point::max(); | |
| 193 |
2/2✓ Branch 0 taken 1528 times.
✓ Branch 1 taken 1072 times.
|
2600 | if (sec != -1) { |
| 194 |
1/2✓ Branch 0 taken 1528 times.
✗ Branch 1 not taken.
|
1528 | timeoutTime = steady_clock::now() + seconds(sec); |
| 195 | } | ||
| 196 |
1/2✓ Branch 0 taken 2600 times.
✗ Branch 1 not taken.
|
2600 | std::unique_lock<std::shared_mutex> lock(warningsLock); |
| 197 |
2/2✓ Branch 0 taken 3482 times.
✓ Branch 1 taken 1616 times.
|
5098 | for (auto it = warnings.begin(); it != warnings.end(); ++it) { |
| 198 |
6/6✓ Branch 0 taken 3233 times.
✓ Branch 1 taken 249 times.
✓ Branch 2 taken 984 times.
✓ Branch 3 taken 2249 times.
✓ Branch 4 taken 984 times.
✓ Branch 5 taken 2498 times.
|
3482 | if (it->id() == id && it->message() == w) { |
| 199 | // Timeout is allowed to move later, but not earlier | ||
| 200 |
3/4✓ Branch 0 taken 984 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 563 times.
✓ Branch 3 taken 421 times.
|
984 | if (timeoutTime > it->timeout) |
| 201 | 563 | it->timeout = timeoutTime; | |
| 202 | 984 | return; | |
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 |
1/2✓ Branch 0 taken 1616 times.
✗ Branch 1 not taken.
|
1616 | auto& ref = warnings.emplace_back(id, w, plugin); |
| 207 |
1/2✓ Branch 0 taken 1616 times.
✗ Branch 1 not taken.
|
1616 | ref.data = data; |
| 208 | |||
| 209 | 1616 | ref.timeout = timeoutTime; | |
| 210 |
3/4✓ Branch 0 taken 1616 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 154 times.
✓ Branch 3 taken 1462 times.
|
1616 | if (timeoutTime < wakeUpTime) { |
| 211 | 154 | wakeUpTime = timeoutTime; | |
| 212 | } | ||
| 213 |
1/2✓ Branch 0 taken 1616 times.
✗ Branch 1 not taken.
|
1616 | lock.unlock(); |
| 214 | |||
| 215 | // Notify Listeners | ||
| 216 | 1616 | sema.release(); | |
| 217 |
2/2✓ Branch 0 taken 1616 times.
✓ Branch 1 taken 984 times.
|
2600 | } |
| 218 | 14779 | void WarningHolder::RemoveWarning(int id, const std::string& w, const std::string& plugin) { | |
| 219 |
1/2✓ Branch 0 taken 14779 times.
✗ Branch 1 not taken.
|
14779 | LogDebug(VB_GENERAL, "Removing Warning: %s\n", w.c_str()); |
| 220 |
1/2✓ Branch 0 taken 14779 times.
✗ Branch 1 not taken.
|
14779 | std::unique_lock<std::shared_mutex> lock(warningsLock); |
| 221 |
2/2✓ Branch 0 taken 4258 times.
✓ Branch 1 taken 13758 times.
|
18016 | for (auto it = warnings.begin(); it != warnings.end(); ++it) { |
| 222 |
7/8✓ Branch 0 taken 1299 times.
✓ Branch 1 taken 2959 times.
✓ Branch 2 taken 1021 times.
✓ Branch 3 taken 278 times.
✓ Branch 4 taken 1021 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1021 times.
✓ Branch 7 taken 3237 times.
|
4258 | if (it->id() == id && it->message() == w && it->plugin() == plugin) { |
| 223 | 1021 | warnings.erase(it); | |
| 224 |
1/2✓ Branch 0 taken 1021 times.
✗ Branch 1 not taken.
|
1021 | lock.unlock(); |
| 225 | // Notify Listeners | ||
| 226 | 1021 | sema.release(); | |
| 227 | 1021 | return; | |
| 228 | } | ||
| 229 | } | ||
| 230 |
2/2✓ Branch 0 taken 13758 times.
✓ Branch 1 taken 1021 times.
|
14779 | } |
| 231 | 1917 | void WarningHolder::UpdateLogLevelWarnings() { | |
| 232 |
3/6✓ Branch 0 taken 1917 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1917 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1917 times.
✗ Branch 5 not taken.
|
7668 | RemoveWarning(2, EXCESSIVE_LOG_LEVEL_WARNING); |
| 233 |
3/6✓ Branch 0 taken 1917 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1917 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1917 times.
✗ Branch 5 not taken.
|
5751 | RemoveWarning(3, DEBUG_LOG_LEVEL_WARNING); |
| 234 | 1917 | int lowestLogLevel = FPPLogger::INSTANCE.MinimumLogLevel(); | |
| 235 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1909 times.
|
1917 | if (lowestLogLevel == LOG_EXCESSIVE) |
| 236 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
24 | AddWarning(2, EXCESSIVE_LOG_LEVEL_WARNING); |
| 237 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 1849 times.
|
1909 | else if (lowestLogLevel == LOG_DEBUG) |
| 238 |
2/4✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
|
166 | AddWarning(3, DEBUG_LOG_LEVEL_WARNING); |
| 239 | 1917 | } | |
| 240 | |||
| 241 | // Comes down by its timeout: a loader that still finds the entry raises it again. | ||
| 242 | static constexpr int INVALID_CONFIG_ENTRY_WARNING_ID = 73; | ||
| 243 | |||
| 244 | 49 | void WarningHolder::InvalidConfigEntry(const std::string& file, const std::string& detail) { | |
| 245 | 49 | LogErr(VB_GENERAL, "%s: skipping an entry that could not be read (%s)\n", file.c_str(), detail.c_str()); | |
| 246 |
4/8✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 49 times.
✗ Branch 7 not taken.
|
49 | AddWarningTimeout(3600, INVALID_CONFIG_ENTRY_WARNING_ID, file + " has an entry that could not be read and was skipped: " + detail); |
| 247 | 49 | } | |
| 248 | |||
| 249 | ✗ | void WarningHolder::RemoveAllWarnings() { | |
| 250 | ✗ | std::unique_lock<std::shared_mutex> lock(warningsLock); | |
| 251 | ✗ | warnings.clear(); | |
| 252 | ✗ | wakeUpTime = steady_clock::time_point::max(); | |
| 253 | ✗ | lock.unlock(); | |
| 254 | |||
| 255 | // Notify Listeners | ||
| 256 | ✗ | sema.release(); | |
| 257 | ✗ | } | |
| 258 | |||
| 259 | 260190 | std::list<FPPWarning> WarningHolder::GetWarnings() { | |
| 260 |
1/2✓ Branch 0 taken 260190 times.
✗ Branch 1 not taken.
|
260190 | std::shared_lock<std::shared_mutex> lock(warningsLock); |
| 261 |
1/2✓ Branch 0 taken 260190 times.
✗ Branch 1 not taken.
|
520380 | return warnings; |
| 262 | 260190 | } | |
| 263 | |||
| 264 | 4411 | void PruneWarnings() { | |
| 265 | // warnings are not stored in a heap or sorted, so we must walk over the warnings to find expired | ||
| 266 |
1/2✓ Branch 0 taken 4411 times.
✗ Branch 1 not taken.
|
4411 | std::unique_lock lock(warningsLock); |
| 267 | 4411 | wakeUpTime = steady_clock::time_point::max(); | |
| 268 |
2/2✓ Branch 0 taken 2424 times.
✓ Branch 1 taken 1987 times.
|
4411 | if (!warnings.empty()) { |
| 269 | 2424 | auto now = steady_clock::now(); | |
| 270 |
2/2✓ Branch 0 taken 4845 times.
✓ Branch 1 taken 2424 times.
|
7269 | for (auto it = warnings.begin(); it != warnings.end(); /* in loop */) { |
| 271 |
3/4✓ Branch 0 taken 4845 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 4842 times.
|
4845 | if (it->timeout <= now) { |
| 272 | // warning has expired | ||
| 273 | 3 | it = warnings.erase(it); | |
| 274 | 3 | continue; | |
| 275 |
3/4✓ Branch 0 taken 4842 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1682 times.
✓ Branch 3 taken 3160 times.
|
4842 | } else if (it->timeout < wakeUpTime) { |
| 276 | // our next warning | ||
| 277 | 1682 | wakeUpTime = it->timeout; | |
| 278 | } | ||
| 279 | 4842 | ++it; | |
| 280 | } | ||
| 281 | } | ||
| 282 | 4411 | } | |
| 283 |