Add log configuration ensure watchdog (#1535)

This commit is contained in:
LoveSy 2022-01-15 23:17:20 +08:00 committed by GitHub
parent 7190a27d70
commit 47d88050d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 119 additions and 15 deletions

View File

@ -1,17 +1,26 @@
#include "logcat.h"
#include <jni.h>
#include <unistd.h>
#include <string>
#include <android/log.h>
#include <array>
#include <cinttypes>
#include "logcat.h"
#include <chrono>
#include <thread>
#include <sys/system_properties.h>
using namespace std::string_view_literals;
using namespace std::chrono_literals;
constexpr size_t kMaxLogSize = 4 * 1024 * 1024;
#ifdef NDEBUG
constexpr size_t kLogBufferSize = 256 * 1024;
#else
constexpr size_t kLogBufferSize = 4 * 1024 * 1024;
#endif
namespace {
constexpr std::array<char, ANDROID_LOG_SILENT + 1> kLogChar = {
/*ANDROID_LOG_UNKNOWN*/'?',
/*ANDROID_LOG_DEFAULT*/ '?',
@ -24,6 +33,60 @@ constexpr std::array<char, ANDROID_LOG_SILENT + 1> kLogChar = {
/*ANDROID_LOG_SILENT*/ 'S',
};
size_t ParseUint(const char *s) {
if (s[0] == '\0') return -1;
while (isspace(*s)) {
s++;
}
if (s[0] == '-') {
return -1;
}
int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
char *end;
auto result = strtoull(s, &end, base);
if (end == s) {
return -1;
}
if (*end != '\0') {
const char *suffixes = "bkmgtpe";
const char *suffix;
if ((suffix = strchr(suffixes, tolower(*end))) == nullptr ||
__builtin_mul_overflow(result, 1ULL << (10 * (suffix - suffixes)), &result)) {
return -1;
}
}
if (std::numeric_limits<size_t>::max() < result) {
return -1;
}
return static_cast<size_t>(result);
}
inline size_t GetByteProp(std::string_view prop, size_t def = -1) {
std::array<char, PROP_VALUE_MAX> buf{};
if (__system_property_get(prop.data(), buf.data()) < 0) return def;
return ParseUint(buf.data());
}
inline std::string GetStrProp(std::string_view prop, std::string def = {}) {
std::array<char, PROP_VALUE_MAX> buf{};
if (__system_property_get(prop.data(), buf.data()) < 0) return def;
return {buf.data()};
}
inline bool SetIntProp(std::string_view prop, int val) {
auto buf = std::to_string(val);
return __system_property_set(prop.data(), buf.data()) >= 0;
}
inline bool SetStrProp(std::string_view prop, std::string_view val) {
return __system_property_set(prop.data(), val.data()) >= 0;
}
} // namespace
class UniqueFile : public std::unique_ptr<FILE, std::function<void(FILE *)>> {
inline static deleter_type deleter = [](auto f) { f && f != stdout && fclose(f); };
public:
@ -52,6 +115,8 @@ private:
static size_t PrintLogLine(const AndroidLogEntry &entry, FILE *out);
void EnsureLogWatchDog();
JNIEnv *env_;
jobject thiz_;
jmethodID refresh_fd_method_;
@ -73,7 +138,7 @@ size_t Logcat::PrintLogLine(const AndroidLogEntry &entry, FILE *out) {
if (!out) return 0;
constexpr static size_t kMaxTimeBuff = 64;
struct tm tm{};
std::array<char, kMaxTimeBuff> time_buff;
std::array<char, kMaxTimeBuff> time_buff{};
auto now = entry.tv_sec;
auto nsec = entry.tv_nsec;
@ -122,8 +187,12 @@ void Logcat::RefreshFd(bool is_verbose) {
}
inline void Logcat::Log(std::string_view str) {
if (verbose_) fprintf(verbose_file_.get(), "%.*s", static_cast<int>(str.size()), str.data());
if (verbose_) {
fprintf(verbose_file_.get(), "%.*s", static_cast<int>(str.size()), str.data());
fflush(verbose_file_.get());
}
fprintf(modules_file_.get(), "%.*s", static_cast<int>(str.size()), str.data());
fflush(modules_file_.get());
}
void Logcat::OnCrash() {
@ -142,7 +211,7 @@ void Logcat::OnCrash() {
Log("\nLogd maybe crashed, retrying in 1s...\n");
}
sleep(1);
std::this_thread::sleep_for(1s);
}
void Logcat::ProcessBuffer(struct log_msg *buf) {
@ -178,11 +247,46 @@ void Logcat::ProcessBuffer(struct log_msg *buf) {
}
}
void Logcat::EnsureLogWatchDog() {
constexpr static auto kLogdSizeProp = "persist.logd.size"sv;
constexpr static auto kLogdTagProp = "persist.log.tag"sv;
constexpr static auto kLogdMainSizeProp = "persist.logd.size.main"sv;
constexpr static auto kLogdCrashSizeProp = "persist.logd.size.crash"sv;
constexpr static size_t kErr = -1;
std::thread([this] {
while (true) {
auto logd_size = GetByteProp(kLogdSizeProp);
auto logd_tag = GetStrProp(kLogdTagProp);
auto logd_main_size = GetByteProp(kLogdMainSizeProp);
auto logd_crash_size = GetByteProp(kLogdCrashSizeProp);
if (!logd_tag.empty() ||
!((logd_main_size == kErr && logd_crash_size == kErr && logd_size != kErr &&
logd_size >= kLogBufferSize) ||
(logd_main_size != kErr && logd_main_size >= kLogBufferSize &&
logd_crash_size != kErr &&
logd_crash_size >= kLogBufferSize))) {
SetIntProp(kLogdSizeProp, kLogBufferSize);
SetIntProp(kLogdMainSizeProp, kLogBufferSize);
SetIntProp(kLogdCrashSizeProp, kLogBufferSize);
SetStrProp(kLogdTagProp, "");
SetStrProp("ctl.start", "logd-reinit");
Log("Reset log settings\n");
}
const auto *pi = __system_property_find(kLogdTagProp.data());
uint32_t serial;
if (!__system_property_wait(pi, 0, &serial, nullptr)) break;
}
}).detach();
}
void Logcat::Run() {
constexpr size_t tail_after_crash = 10U;
size_t tail = 0;
RefreshFd(true);
RefreshFd(false);
EnsureLogWatchDog();
while (true) {
std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
android_logger_list_alloc(0, tail, 0), &android_logger_list_free};