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:
1 parent
29e1b35da8
commit
2d93298f8a
7 files changed
+272
-8
No files matched your search
@@ -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) */
|
||||
|
||||
Reference in new issue
Block a user