diff --git a/patch_v2/meow_amsd/meow_amsd b/patch_v2/meow_amsd/meow_amsd index 741b9d1..9330bbe 100755 Binary files a/patch_v2/meow_amsd/meow_amsd and b/patch_v2/meow_amsd/meow_amsd differ diff --git a/patch_v2/meow_amsd/meow_amsd.c b/patch_v2/meow_amsd/meow_amsd.c index 5023a70..f07f694 100644 --- a/patch_v2/meow_amsd/meow_amsd.c +++ b/patch_v2/meow_amsd/meow_amsd.c @@ -65,6 +65,9 @@ #define AMS_SOCK_PATH_MAX 108 #define AMS_BOOTTS_LEN 64 #define AMS_REQ_MAX 512 /* 命令响应缓冲 */ +#define AMS_IPC_TIMEOUT_MS 1200 /* launcher IPC 单次收发超时:amsd 绝不为一次转发阻塞无限久 */ +#define AMS_IPC_RETRY 2 /* launcher 一次性不可达/超时 → 短退避重连一次 */ +#define AMS_IPC_BACKOFF_MS 250 /* 重连退避基数 */ /* 每 App 状态(一期:STOPPED/FG;BG 预留二期) */ enum { AMS_STOPPED = 0, AMS_FG = 1, AMS_BG = 2 }; @@ -735,6 +738,15 @@ static int ipc_xchg(uint16_t type, const void *payload, uint32_t len, { int fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) return -1; + /* 收发加超时:launcher 刚刚重启/主循环未就绪(接受但不回包)时,amsd 的阻塞 + * read 会永远挂起,冻结整个单线程守护。设 SO_SNDTIMEO/SO_RCVTIMEO 让单次转发 + * 有界,超时即返回失败 → ams_request_ctl 退避重连,绝不无限阻塞。 + * 注意:tv_usec 必须 < 1000000(否则 setsockopt 返回 EINVAL,超时静默失效)。 */ + struct timeval tv; + tv.tv_sec = AMS_IPC_TIMEOUT_MS / 1000; + tv.tv_usec = (AMS_IPC_TIMEOUT_MS % 1000) * 1000; + (void)setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv); + (void)setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv); struct sockaddr_un a; memset(&a, 0, sizeof a); a.sun_family = AF_UNIX; @@ -781,18 +793,25 @@ static int ipc_xchg(uint16_t type, const void *payload, uint32_t len, return (int)rtype; } -/* 向 launcher 申请 start/kill。返回 0=launcher 回 code(a_out 输出);-1=launcher 不通。 */ +/* 向 launcher 申请 start/kill。返回 0=launcher 回 code(a_out 输出);-1=launcher 不通。 + * launcher 重启窗口(svcd/sysui 重启 launcher、或 amsd 先行启动)内连接会暂不可达/超时: + * 这里做「指数式短退避重试」——launcher 数秒内回来即自动恢复转发(无需人工重发)。 */ static int ams_request_ctl(uint16_t type, const void *payload, uint32_t len, uint32_t *code) { uint8_t rbuf[64]; - int rt = ipc_xchg(type, payload, len, rbuf, sizeof rbuf); - if (rt == MSG_ACK) { - m_ack_t a; - memcpy(&a, rbuf, sizeof a); - if (code) *code = a.code; - return 0; + for (int attempt = 0; attempt < AMS_IPC_RETRY; attempt++) { + int rt = ipc_xchg(type, payload, len, rbuf, sizeof rbuf); + if (rt == MSG_ACK) { + m_ack_t a; + memcpy(&a, rbuf, sizeof a); + if (code) *code = a.code; + return 0; + } + if (rt == MSG_ERR) return MEOW_ERR_INTERNAL; + /* 一次连接失败/超时(launcher 未就绪)→ 短退避再试;仍失败则返回 -1。 */ + if (attempt + 1 < AMS_IPC_RETRY) + usleep((useconds_t)(AMS_IPC_BACKOFF_MS * (attempt + 1)) * 1000); } - if (rt == MSG_ERR) return MEOW_ERR_INTERNAL; return -1; } @@ -1364,6 +1383,11 @@ static int run_daemon(void) unsigned long long last_cleanup = 0; while (!g_shutdown) { + /* 每圈清零:谨防上一轮已关闭连接残留的 POLLHUP/POLLERR 落在 pfds[2+i] 上。 + * 若不清,accept 后同一轮就用「陈旧 revents」处理新连接——误判其 HUP/ERR + * 而提前 close(am CLI 收到 SIGPIPE、命令被丢弃),launcher 重启后 EV 事件 + * 连接密集必触发,表现为 `am start` 不再转发到 launcher。 */ + memset(pfds, 0, sizeof pfds); pfds[0].fd = g_listen_fd; pfds[0].events = POLLIN; pfds[0].revents = 0; pfds[1].fd = g_sigpipe[0]; pfds[1].events = POLLIN; pfds[1].revents = 0; for (int i = 0; i < nfds - 2; i++) { diff --git a/patch_v2/meow_amsd/meow_amsd_host b/patch_v2/meow_amsd/meow_amsd_host index 4ae1826..16be5e3 100755 Binary files a/patch_v2/meow_amsd/meow_amsd_host and b/patch_v2/meow_amsd/meow_amsd_host differ