fix(ncm): 播放页歌词解析栈溢出(SIGSEGV)修复 —— lyric_parse 栈上 227KB 临时数组超 128KB 线程栈
根因(真机 sig=11,RA 落 lyric_parse / pc 在 lib): app/logic/lyric.c lyric_parse() 在栈上定义 long ttmp[NCM_LYRIC_LINES=600]; char txt[600][192]; char tl[600][192] = ~227KB 栈帧,远超 ncm_thread_create 统一设的 NCM_THREAD_STACK=128KB。 播放页 enter → player_manager_load_lyric → lyric_worker(128KB 线程栈) → lyric_parse → 栈溢出 SIGSEGV。 崩溃仅在「播放页前台 + 拉取歌词成功 + 解析」时触发,故与播放进度无关、autoplay 仅后台起播不崩。 修法:排序临时数组移到堆(按 s_n 计,≤600 行,峰值 ~230KB 瞬态),栈帧回到 KB 级。 复现/定位(/dev 调试 + 真机): - 真机通过 amd 恢复路径:/tmp/ncm_autoplay 起播缓存曲,app_on_tick 于 UI 线程调 player_play_song 打开播放页(复现用户点曲路径;autoplay_ui_consume 承接)。原崩溃:pid sig=11 dur=3683ms; 修复后:连续两次 play:start 无崩溃、60s+ 存活、无 crash_report。 - app.c 增 async-signal-safe SIGSEGV/SIGBUS/SIGILL 处理器(MIPS mcontext_t.pc + gregs ra/sp/fp → stderr + crash_report.txt),供 addr2line/链接布局定位。 验证:stream/player_flow/window/search/cache_evict sim 全 PASS;test_ncm_core host + qemu-mipsel PASS;build_ncm.sh -Wall -Wextra 0 warning;ncm_host NCM_PAGE=player/home 离屏渲染 exit=0。
This commit is contained in:
1 parent
54750a63c5
commit
bcc016e50e
6 files changed
+101
-18
No files matched your search
@@ -9,6 +9,11 @@
|
||||
*/
|
||||
#include "ncm_app_internal.h"
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
ncm_app_state_t g_st;
|
||||
ncm_play_run_t g_play = { .mu = PTHREAD_MUTEX_INITIALIZER,
|
||||
@@ -22,6 +27,53 @@ static meow_view *g_login_view, *g_home_view, *g_pl_view, *g_plr_view, *g_set_vi
|
||||
|
||||
static void on_sigterm(int s) { (void)s; meow_ui_request_exit(); }
|
||||
|
||||
/* SIGSEGV/SIGBUS/SIGILL 定位处理器(真机复现调试用):**必须 async-signal-safe**(只 write+_exit,
|
||||
* 手写十六进制格式化,不用 snprintf/sprintf——后者内部取锁,在信号上下文可能自锁死)。把
|
||||
* si_addr + 中断点 pc + ra/sp/fp(MIPS O32:mcontext_t.pc / gregs[31 ra][29 sp][30 fp])
|
||||
* 写 stderr(amsd 捕获)+ 固定文件,配合 nm/链接布局定位崩溃函数。 */
|
||||
static void fatal_sig_report(int sig, siginfo_t *si, void *ctx)
|
||||
{
|
||||
ucontext_t *uc = (ucontext_t *)ctx;
|
||||
unsigned long long v = 0;
|
||||
unsigned char b[192];
|
||||
int o = 0;
|
||||
const char *tag = (sig == SIGSEGV) ? "SIGSEGV" : (sig == SIGBUS ? "SIGBUS" : "SIGILL");
|
||||
#define FATAL_PUTS(s) do { const char *_p = (s); while (*_p) b[o++] = (unsigned char)*_p++; } while (0)
|
||||
#define FATAL_HEX(x) do { unsigned long long _v = (unsigned long long)(x); \
|
||||
int _sh; \
|
||||
for (_sh = 28; _sh >= 0; _sh -= 4) b[o++] = \
|
||||
(unsigned char)"0123456789abcdef"[(_v >> _sh) & 15]; } while (0)
|
||||
#define FATAL_STR(h, x) do { FATAL_PUTS(h); FATAL_HEX(x); } while (0)
|
||||
FATAL_PUTS("\nFATAL "); FATAL_PUTS(tag);
|
||||
FATAL_PUTS(" sig="); FATAL_HEX(sig);
|
||||
v = (unsigned long long)(uintptr_t)si->si_addr; FATAL_STR(" addr=", v);
|
||||
v = uc->uc_mcontext.pc; FATAL_STR(" pc=", v);
|
||||
v = uc->uc_mcontext.gregs[31]; FATAL_STR(" ra=", v);
|
||||
v = uc->uc_mcontext.gregs[29]; FATAL_STR(" sp=", v);
|
||||
v = uc->uc_mcontext.gregs[30]; FATAL_STR(" fp=", v);
|
||||
FATAL_PUTS("\n");
|
||||
#undef FATAL_PUTS
|
||||
#undef FATAL_HEX
|
||||
#undef FATAL_STR
|
||||
(void)write(2, b, (size_t)o);
|
||||
int fd = open("/usr/data/mnt/sd_0/MeowOS/logs/dev.player.ncm/crash_report.txt",
|
||||
O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd >= 0) { (void)write(fd, b, (size_t)o); close(fd); }
|
||||
_exit(128 + sig);
|
||||
}
|
||||
|
||||
static void fatal_sig_install(void)
|
||||
{
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof sa);
|
||||
sa.sa_sigaction = fatal_sig_report;
|
||||
sa.sa_flags = SA_SIGINFO; /* 不置 SA_NODEFER:防信号内重入 */
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(SIGSEGV, &sa, NULL);
|
||||
sigaction(SIGBUS, &sa, NULL);
|
||||
sigaction(SIGILL, &sa, NULL);
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
/* 事件分发:meow_ui_run 平铺回调 → 当前页 */
|
||||
/* ============================================================ */
|
||||
@@ -89,6 +141,11 @@ static void app_on_tick(void)
|
||||
{
|
||||
uint64_t now = meow_ui_time_ms();
|
||||
autoplay_maybe(); /* 真机联调 hook:/tmp/ncm_autoplay 存在则自动播已缓存曲目(一次性) */
|
||||
/* autoplay 已在后台线程起播缓存曲 → 在此(UI 线程)打开播放页,复现用户点曲播放路径 */
|
||||
{
|
||||
int ai = autoplay_ui_consume();
|
||||
if (ai >= 0) player_play_song(ai);
|
||||
}
|
||||
if (login_is_active()) { login_tick(now); return; }
|
||||
if (player_is_active()) { player_tick(now); return; }
|
||||
if (search_is_active()) { search_tick(now); return; }
|
||||
@@ -110,6 +167,7 @@ int main(void)
|
||||
g_dark = (meow_theme_get_mode() == MEOW_THEME_DARK);
|
||||
meow_theme_add_listener(ncm_on_theme);
|
||||
signal(SIGTERM, on_sigterm);
|
||||
fatal_sig_install(); /* SIGSEGV/SIGBUS/SIGILL 写崩溃地址定位(真机复现调试) */
|
||||
|
||||
/* 应用数据/核心库上下文(cookie/deviceId/cache/设置) */
|
||||
appstate_init();
|
||||
|
||||
Reference in new issue
Block a user