feat(launcher): 通知查询/清除 IPC + App崩溃直报crash (agent-199) — MSG_NOTIFY_QUERY(0x25)/QUERY_RESULT(0x27)/DISMISS_ALL(0x26,保留媒体/进度/常驻红线), DISMISS(0x22)复用既有; 序列化在主循环单写者做; launch_app waitpid 回收处 notify_app_crash(信号杀/非0退出上报 /tmp/meow_crash.sock best-effort, 干净exit不报)

launcher 61f6b0db→3c7c2ec7; qemu IPC 往返+宿主存储单测+mock crash socket 全过; 顺带清理既有告警(util.c/app_launcher.c/meow_ipc.c)
This commit is contained in:
MeowOS committed 2026-08-31 05:46:46 +08:00
1 parent 29e1b35da8
commit 2d93298f8a
7 files changed
+272 -8

No files matched your search

+50 -1
View File
@@ -771,6 +771,50 @@ static void app_overlay_statusbar(void)
/* (definition follows) */
#define MEOW_CRASH_SOCK "/tmp/meow_crash.sock" /* meow_crash 崩溃上报 socket(best-effort,见 meow_crash.md §2)*/
/* App 异常退出(信号杀 / 非 0 退出码)→ best-effort 直报 meow_crash。
* 格式:`app <pkg> sig=<n>` / `app <pkg> exit=<n>`(参照 svcd notify_crash(),但用 app 域前缀)。
* 全程非阻塞:socket O_NONBLOCK;connect 失败即弃;EINPROGRESS 短 poll(POLLOUT) ≤150ms 排空,
* 仍不可写即丢弃;单行小消息一次 write(失败即弃),绝不重试。meow_crash 不在线 → 静默丢,
* 绝不拖垮 launcher。调用方负责只对异常退出调用(干净 exit(0) 不上报)。 */
static void notify_app_crash(const char *pkg, int status)
{
const char *kind;
int num;
if (WIFSIGNALED(status)) { kind = "sig"; num = WTERMSIG(status); }
else { kind = "exit"; num = WIFEXITED(status) ? WEXITSTATUS(status) : 1; }
char msg[192];
int len = snprintf(msg, sizeof msg, "app %s %s=%d\n", pkg, kind, num);
if (len <= 0) return;
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) return;
int fl = fcntl(fd, F_GETFL, 0);
if (fl >= 0) fcntl(fd, F_SETFL, fl | O_NONBLOCK);
struct sockaddr_un a;
memset(&a, 0, sizeof a);
a.sun_family = AF_UNIX;
strncpy(a.sun_path, MEOW_CRASH_SOCK, sizeof a.sun_path - 1);
if (connect(fd, (struct sockaddr *)&a, sizeof a) != 0) {
if (errno == EINPROGRESS || errno == EWOULDBLOCK) {
struct pollfd pf;
pf.fd = fd; pf.events = POLLOUT; pf.revents = 0;
int r = poll(&pf, 1, 150);
if (r <= 0 || !(pf.revents & POLLOUT)) { close(fd); return; }
} else {
close(fd);
return; /* crash 不在线:静默丢 */
}
}
ssize_t w = write(fd, msg, (size_t)len);
(void)w;
close(fd);
}
int launch_app(struct app *a)
{
logmsg("launch: %s (%s)", a->name, a->exec);
@@ -939,7 +983,7 @@ int launch_app(struct app *a)
meow_write_app_state(a->immersive == '1' ? 1 : 0);
/* watchdog for virtual back key / gestures */
char wd1[192], wd2[192], pidstr[16];
char wd1[192], pidstr[16];
pid_t wpid = 0;
snprintf(pidstr, sizeof pidstr, "%d", pid);
if (access(WATCHDOG1, X_OK) == 0)
@@ -1134,6 +1178,11 @@ int launch_app(struct app *a)
/* 顶条收合/恢复过渡期把循环睡得短些(~20ms),驱动更平滑的上移出屏;稳定后回 100ms。 */
usleep(meow_ui_statusbar_animating() ? 20000 : 100000);
}
/* M2.x:App 异常退出(信号杀 / 非 0 退出码)→ best-effort 直报 meow_crash。
* 判据与 svcd reap_children 一致:failed = !(WIFEXITED && WEXITSTATUS==0)。干净 exit(0)
* 不上报;sigterm 关停/电源菜单重启路径 status 保持 0(未 waitpid)→ 视为干净退出不上报。 */
if (!(WIFEXITED(status) && WEXITSTATUS(status) == 0))
notify_app_crash(a->id, status);
if (wpid > 0) {
/* reap the watchdog: SIGTERM then wait up to 2s (it exits when the
* app dies; bounded so we never hang if it is stuck) */