feat: M6.10–M6.19 批量收编 + M6.19 推卡验收

- M7 launcher 重写 5 期(虚拟化宫格/meow_theme 单一权威/横幅动画/自定义 PIN 键盘)
- OOM 通用化(cachegov 上收 SDK)、自动切歌根治、meowpanel jv_free 泄漏修复、Hello 滚动卡顿修复
- ncm 歌词 UI / 媒体通知封面 / 封面分辨率 640
- 5 bug 修复:ncm 后台化 UI 叠层+点击穿透、再进 ncm 桌面叠层、播放页新旧 UI 叠层抢刷脏区(meow_ui_gfx 恢复边沿整帧重画)、PIN 亮屏亮度跳(keys.c meow_panel_on 按 settings_brightness_clamped 恢复)、通知中心封面显歌单封面(cover.c save_cover_raw 加 is_song + 命中块守卫)
- 四 App 统一重链新 meow_ui.a 51caee4a;M6.19=0.8.19 固件 2d2331f2 推卡自刷验收全绿
This commit is contained in:
AskaEth committed 2026-09-03 12:16:01 +08:00
1 parent c2ee7626a4
commit 3d70a3dd2c
176 files changed
+15507 -597

No files matched your search

+5 -1
View File
@@ -1367,7 +1367,11 @@ static void *io_thread(void *arg)
memcpy(snaps, pfds, sizeof snaps);
pthread_mutex_lock(&g_mu);
(void)pr;
/* 处理 listen */
/* 处理 listen:一次 poll 收 1 个连接。**不可改用「while accept 排空积压」**——在连接
* 风暴下(对端持续 connect)accept 永不 EAGAIN → 持 g_mu 无限循环 → IO 线程卡死、
* 播放/路由/QUERY 全部被 g_mu 阻塞(宿主 T10 实测:drain 版风暴下 probe/OPEN 全 FAIL)。
* 单次 accept + 下一轮 poll 再收,既有界又保持 listener/IO 可服务(原版行为即正确,
* fd=N 反复 accept 是**对端短连接**所致,非本循环缺陷)。 */
if ((snaps[0].revents & POLLIN)) {
int cfd = accept(lfd, NULL, NULL);
if (cfd >= 0) {
Binary file not shown.
+38 -1
View File
@@ -651,7 +651,44 @@ int main(void)
check(0, "pipe for T9 child");
}
}
stop_audiod();
/* ---- T10:连接表溢出丢弃护栏与回收(回归 fd=N accept 风暴,§2026-09-02 真机 1489 次)。
* 背景:CLI_MAX=8(§12「客户端全有界」护栏)。ncm「每次 audio_out_open 新建一条短连接」
* (旧 audio_out_sync_volume)在边下边播/切歌 churn 下会反复占用连接槽:8 张表占满后,
* 新 connect 的 accept 因 cli_alloc 失败被**安全丢弃**(日志 "client limit reached, drop"),
* 表回收后 NEW 连接照常服务。本用例:
* ① 洪泛 connect→write→close ×60(远超 CLI_MAX=8,走上述 drop 护栏);
* ② 断言 audiod **不 wedge/不崩**(此后 SIGTERM 干净退出);
* ③ 等表回收(短连接已 close,EOF 逐 poll 回收)后,新 OPEN 仍被授权(fd 复用回收)。
* 「同一 fd=N 被反复 accept」= 对端短连接 + fd 低位复用,本是**正常回收机理**,非循环缺陷;
* 根因在对端每 open 建新连接,由 ncm side audio_out.c「音量同步每进程一次」消除(vol_sync_sim)。 ---- */
printf("[T10 client-table overflow guard & recycle]\n");
unlink(TSOCK);
g_audiod_pid = start_audiod_ex("null", NULL, NULL);
usleep(400000);
int burst = 0;
for (int i = 0; i < 60; i++) { /* 洪泛 > CLI_MAX=8 */
struct cli v;
if (cli_connect(&v) == 0) {
int32_t pct = 50;
if (sf(v.fd, MSG_AUDIO_VOLUME, 7, &pct, sizeof pct) == 0) burst++;
close(v.fd); /* 对端读 EOF → cli_free 回收 */
}
}
printf(" issued=%d/60 (cap by CLI_MAX=8 overflow drops)\n", burst);
check(burst > 0, "connections issued (overflow hits drop guard)");
/* ③ 等表回收(≤1s:EOF 逐 poll 回收)后新 OPEN 仍被授权 */
usleep(700000);
int eok = 0;
{
struct cli e;
if (cli_connect(&e) == 0) {
m_audio_open_ack_t ak;
if (do_open(&e, 48000, 2, AUDIO_FMT_S16, &ak) == 0 && ak.err == MEOW_OK) eok = 1;
close(e.fd);
}
}
check(eok, "fresh OPEN after overflow (table recycled, no exhaustion/wedge)");
check(stop_audiod_tmo(5000) != 0, "audiod not wedged by overflow (SIGTERM clean exit)");
printf("=== SUMMARY: pass=%d fail=%d ===\n", g_pass, g_fail);
return g_fail ? 1 : 0;