feat(watchdog): M52 资源压力可观测 + multi_font 日志去刷屏 + audiod bind 失败即退

- watchdog(新 wd_resguard.h + meow_watchdog.c):每 10s 采 /proc/meminfo
  (MemFree/MemAvailable)、进程总数、单父进程子进程数前 5 名;过阈值时向
  MeowOS/logs 打 RESGUARD 告警,带等级/命中规则/进程名+PID 名单。零 fork、零堆分配、
  不发任何信号(只报警)。阈值依据 = 真机实测 56872kB / 空闲 100 进程 / maxch=11,
  推导写在 wd_resguard.h 文件头;日志只在等级跃迁或同态每 5 分钟复述。
- launcherd:multi_font 那行「每 2s 无条件打一条」改为只在配置签名跃迁时打
  (新 mf_logsig.h 纯函数 + test_mf_logsig 宿主单测,接进 build_launcher.sh test)。
  真机 6603 行日志里该行占 5297 行(80%)。
- audiod:io bind 失败不再只记一行就 return(旧行为让主线程 watchdog 空转 720s、
  客户端全 ECONNREFUSED),改为明确报错 + g_stop 干净退出;仅动 io_thread 一个 hunk。
This commit is contained in:
AskaEth committed 2026-11-12 08:02:22 +08:00
1 parent f3d7b386b2
commit 166b32d0e5
8 files changed
+755 -4

No files matched your search

+65
View File
@@ -0,0 +1,65 @@
/* mf_logsig.h — 多字体配置的「日志跃迁签名」(纯函数,宿主可单测)。
*
* 为什么需要它(M52):meow_font_reload_multifont() 由 launcher 主循环的 hotplug 轮询
* 每 2s 调一次(main_menu.c),而多字体配置在绝大多数周期里毫无变化。旧实现无条件打
* `multi_font: enabled, %d distinct fonts (global=%s)`,真机 meow_20261111_154540.log
* 6603 行里 5297 行是它(80%,~291KB/406KB),把事故现场唯一的信号淹没了。
*
* 修法不是删日志(首次启用/用户改字体必须留痕),而是把它绑到**配置签名**上:签名变了
* 才打。签名覆盖所有能改变多字体行为的输入 ——
* on(display.multi_font)、全局字体 png(font.file → 生效档)、6 个 font.class_* 的
* 解析后绝对路径、distinct(实际驻留套数)、truncated(超预算截断)。
* 因此「字体集合或 global font 变化」必然换签名,纯粹的时间流逝不会。
*/
#ifndef MF_LOGSIG_H
#define MF_LOGSIG_H
#include <stdint.h>
#include <stdio.h>
#define MF_LOGSIG_SEED 14695981039346656037ULL /* FNV-1a 64 offset basis */
#define MF_LOGSIG_PRIME 1099511628211ULL
/* 把一段字符串折进签名。字段之间补分隔符,防 ("ab","c") 与 ("a","bc") 撞同一值。
* NULL 与 "" 视为同一(配置项为空 = 该类别用全局字体)。 */
static inline uint64_t mf_logsig_mix(uint64_t h, const char *s)
{
if (!s) s = "";
while (*s) {
h ^= (uint64_t)(unsigned char)*s++;
h *= MF_LOGSIG_PRIME;
}
h ^= 0x1f; /* 字段分隔(0x1f = US,不会出现在路径里) */
h *= MF_LOGSIG_PRIME;
return h;
}
/* 多字体配置签名。ncls = 类别数(MEOW_FCLS_COUNT=6),cpng[c] 可为 NULL。
* distinct < 0 表示 config 失败(此时 distinct 无意义,用 -1 编码「失败」)。 */
static inline uint64_t mf_logsig(int on, const char *gpng,
const char *const *cpng, int ncls,
int distinct, int truncated)
{
char num[24];
uint64_t h = MF_LOGSIG_SEED;
snprintf(num, sizeof num, "%d", on ? 1 : 0);
h = mf_logsig_mix(h, num);
h = mf_logsig_mix(h, gpng);
for (int c = 0; c < ncls; c++)
h = mf_logsig_mix(h, (cpng && cpng[c]) ? cpng[c] : "");
snprintf(num, sizeof num, "%d:%d", distinct, truncated ? 1 : 0);
h = mf_logsig_mix(h, num);
return h;
}
/* 日志门控:首次(*valid=0)或签名变化 → 返回 1 并记下;同一签名重复调用 → 0。
* 调用方持有 *last / *valid(文件级静态),因此这就是「只在跃迁时打日志」的全部判定。 */
static inline int mf_logsig_changed(uint64_t *last, int *valid, uint64_t sig)
{
if (*valid && sig == *last) return 0;
*last = sig;
*valid = 1;
return 1;
}
#endif /* MF_LOGSIG_H */