Add log configuration ensure watchdog (#1535)
This commit is contained in:
parent
7190a27d70
commit
47d88050d3
|
|
@ -1,28 +1,91 @@
|
|||
#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
|
||||
|
||||
constexpr std::array<char, ANDROID_LOG_SILENT + 1> kLogChar = {
|
||||
/*ANDROID_LOG_UNKNOWN*/'?',
|
||||
/*ANDROID_LOG_DEFAULT*/ '?',
|
||||
/*ANDROID_LOG_VERBOSE*/ 'V',
|
||||
/*ANDROID_LOG_DEBUG*/ 'D',
|
||||
/*ANDROID_LOG_INFO*/'I',
|
||||
/*ANDROID_LOG_WARN*/'W',
|
||||
/*ANDROID_LOG_ERROR*/ 'E',
|
||||
/*ANDROID_LOG_FATAL*/ 'F',
|
||||
/*ANDROID_LOG_SILENT*/ 'S',
|
||||
};
|
||||
namespace {
|
||||
constexpr std::array<char, ANDROID_LOG_SILENT + 1> kLogChar = {
|
||||
/*ANDROID_LOG_UNKNOWN*/'?',
|
||||
/*ANDROID_LOG_DEFAULT*/ '?',
|
||||
/*ANDROID_LOG_VERBOSE*/ 'V',
|
||||
/*ANDROID_LOG_DEBUG*/ 'D',
|
||||
/*ANDROID_LOG_INFO*/'I',
|
||||
/*ANDROID_LOG_WARN*/'W',
|
||||
/*ANDROID_LOG_ERROR*/ 'E',
|
||||
/*ANDROID_LOG_FATAL*/ 'F',
|
||||
/*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); };
|
||||
|
|
@ -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};
|
||||
|
|
|
|||
Loading…
Reference in New Issue