Fix log watchdog logic

Log watchdog is meant to revert changes to the system prop
`persist.log.tag`, which sets global log level, see docs at
https://cs.android.com/android/platform/superproject/main/+/main:system/logging/logd/README.property

Current commit fixes the following:
1. avoid recast size value `-1` to unsigned integer type size_t;
2. allow the `Enable log watchdog` to removed added system prop and
   restart the watchdog forcely.
This commit is contained in:
JingMatrix 2024-12-08 23:38:20 +01:00
parent fd3f76324e
commit 8dff17c1f9
1 changed files with 28 additions and 15 deletions

View File

@ -7,8 +7,6 @@
#include <array> #include <array>
#include <atomic> #include <atomic>
#include <chrono>
#include <cinttypes>
#include <functional> #include <functional>
#include <string> #include <string>
#include <thread> #include <thread>
@ -17,7 +15,7 @@ using namespace std::string_view_literals;
using namespace std::chrono_literals; using namespace std::chrono_literals;
constexpr size_t kMaxLogSize = 4 * 1024 * 1024; constexpr size_t kMaxLogSize = 4 * 1024 * 1024;
constexpr size_t kLogBufferSize = 64 * 1024; constexpr long kLogBufferSize = 64 * 1024;
namespace { namespace {
constexpr std::array<char, ANDROID_LOG_SILENT + 1> kLogChar = { constexpr std::array<char, ANDROID_LOG_SILENT + 1> kLogChar = {
@ -32,7 +30,7 @@ constexpr std::array<char, ANDROID_LOG_SILENT + 1> kLogChar = {
/*ANDROID_LOG_SILENT*/ 'S', /*ANDROID_LOG_SILENT*/ 'S',
}; };
size_t ParseUint(const char *s) { long ParseUint(const char *s) {
if (s[0] == '\0') return -1; if (s[0] == '\0') return -1;
while (isspace(*s)) { while (isspace(*s)) {
@ -63,7 +61,7 @@ size_t ParseUint(const char *s) {
return static_cast<size_t>(result); return static_cast<size_t>(result);
} }
inline size_t GetByteProp(std::string_view prop, size_t def = -1) { inline long GetByteProp(std::string_view prop, long def = -1) {
std::array<char, PROP_VALUE_MAX> buf{}; std::array<char, PROP_VALUE_MAX> buf{};
if (__system_property_get(prop.data(), buf.data()) < 0) return def; if (__system_property_get(prop.data(), buf.data()) < 0) return def;
return ParseUint(buf.data()); return ParseUint(buf.data());
@ -247,9 +245,17 @@ void Logcat::ProcessBuffer(struct log_msg *buf) {
} else if (msg == "!!start_watchdog!!"sv) { } else if (msg == "!!start_watchdog!!"sv) {
enable_watchdog = true; enable_watchdog = true;
enable_watchdog.notify_one(); enable_watchdog.notify_one();
EnsureLogWatchDog();
} else if (msg == "!!stop_watchdog!!"sv) { } else if (msg == "!!stop_watchdog!!"sv) {
enable_watchdog = false; enable_watchdog = false;
enable_watchdog.notify_one(); enable_watchdog.notify_one();
std::system("resetprop -p --delete persist.logd.size");
std::system("resetprop -p --delete persist.logd.size.main");
std::system("resetprop -p --delete persist.logd.size.crash");
// Terminate the watchdog thread by exiting __system_property_wait firs firstt
std::system("setprop persist.log.tag V");
std::system("resetprop -p --delete persist.log.tag");
} }
} }
} }
@ -259,14 +265,17 @@ void Logcat::EnsureLogWatchDog() {
constexpr static auto kLogdTagProp = "persist.log.tag"sv; constexpr static auto kLogdTagProp = "persist.log.tag"sv;
constexpr static auto kLogdMainSizeProp = "persist.logd.size.main"sv; constexpr static auto kLogdMainSizeProp = "persist.logd.size.main"sv;
constexpr static auto kLogdCrashSizeProp = "persist.logd.size.crash"sv; constexpr static auto kLogdCrashSizeProp = "persist.logd.size.crash"sv;
constexpr static size_t kErr = -1; constexpr static long kErr = -1;
std::thread watch_dog([this] { std::thread watchdog([this] {
while (true) { while (true) {
enable_watchdog.wait(false); enable_watchdog.wait(false); // Blocking current thread until enable_watchdog is true;
auto logd_size = GetByteProp(kLogdSizeProp); auto logd_size = GetByteProp(kLogdSizeProp);
auto logd_tag = GetStrProp(kLogdTagProp); auto logd_tag = GetStrProp(kLogdTagProp);
auto logd_main_size = GetByteProp(kLogdMainSizeProp); auto logd_main_size = GetByteProp(kLogdMainSizeProp);
auto logd_crash_size = GetByteProp(kLogdCrashSizeProp); auto logd_crash_size = GetByteProp(kLogdCrashSizeProp);
Log("[LogWatchDog started] log.tag: " + logd_tag +
"; logd.[default, main, crash].size: [" + std::to_string(logd_size) + "," +
std::to_string(logd_main_size) + "," + std::to_string(logd_crash_size) + "]\n");
if (!logd_tag.empty() || if (!logd_tag.empty() ||
!((logd_main_size == kErr && logd_crash_size == kErr && logd_size != kErr && !((logd_main_size == kErr && logd_crash_size == kErr && logd_size != kErr &&
logd_size >= kLogBufferSize) || logd_size >= kLogBufferSize) ||
@ -287,14 +296,20 @@ void Logcat::EnsureLogWatchDog() {
} }
if (!__system_property_wait(pi, serial, &serial, nullptr)) break; if (!__system_property_wait(pi, serial, &serial, nullptr)) break;
if (pi != nullptr) { if (pi != nullptr) {
if (enable_watchdog) Log("\nResetting log settings\n"); if (enable_watchdog) {
} else Log("\nProp persist.log.tag changed, resetting log settings\n");
} else {
break; // End current thread as expected
}
} else {
// log tag prop was not found; to avoid frequently trigger wait, sleep for a while
std::this_thread::sleep_for(1s); std::this_thread::sleep_for(1s);
// log tag prop was not found; to avoid frequently trigger wait, sleep for a while }
} }
Log("[LogWatchDog stopped]\n");
}); });
pthread_setname_np(watch_dog.native_handle(), "watchdog"); pthread_setname_np(watchdog.native_handle(), "watchdog");
watch_dog.detach(); watchdog.detach();
} }
void Logcat::Run() { void Logcat::Run() {
@ -303,8 +318,6 @@ void Logcat::Run() {
RefreshFd(true); RefreshFd(true);
RefreshFd(false); RefreshFd(false);
EnsureLogWatchDog();
while (true) { while (true) {
std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{ std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
android_logger_list_alloc(0, tail, 0), &android_logger_list_free}; android_logger_list_alloc(0, tail, 0), &android_logger_list_free};