From 3cc4e35794cb0e6b1c2244d6135b3e3f1059436e Mon Sep 17 00:00:00 2001 From: MeowOS Date: Mon, 31 Aug 2026 05:30:04 +0800 Subject: [PATCH] =?UTF-8?q?fix(sdk):=20App=20=E9=80=80=E5=87=BA=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E5=85=9C=E5=BA=95=20=E2=80=94=20meow=5Fui=5Finit=20?= =?UTF-8?q?=E5=AE=89=E8=A3=85=20SIGTERM/SIGINT=20=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=99=A8(log=5Fsig=5Fexit:=20=E7=9B=B4=E5=86=99=20exit:sigterm?= =?UTF-8?q?=20=E7=BB=95=E8=BF=87=E7=BC=93=E5=86=B2+exit(0))=EF=BC=9B?= =?UTF-8?q?=E4=BF=AE=20watchdog=20=E8=BF=94=E5=9B=9E=E9=94=AE=E6=9D=80=20A?= =?UTF-8?q?pp=20=E6=97=B6=E6=97=A5=E5=BF=97=E5=8F=AA=E6=9C=89=20start=20?= =?UTF-8?q?=E6=B2=A1=E6=9C=89=20exit=20=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=9BApp=20=E8=87=AA=E8=A3=85=E5=A4=84=E7=90=86=E5=99=A8(he?= =?UTF-8?q?llo=20BYE)=E8=A6=86=E7=9B=96=E4=B8=8D=E5=8F=97=E5=BD=B1?= =?UTF-8?q?=E5=93=8D=20+=20meow=5Fui.h=20=E6=97=A7=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E6=B3=A8=E9=87=8A=E6=9B=B4=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit meow_ui.a→049fa9db; hello→d0ac55cf; files→3b3bea05; launcher→4f223701; 宿主 widgets PASS --- meow_ui.h | 2 +- meow_ui_gfx.c | 1 + meow_ui_internal.h | 3 +++ meow_ui_log.c | 25 +++++++++++++++++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/meow_ui.h b/meow_ui.h index d2a2f7b..0a21284 100644 --- a/meow_ui.h +++ b/meow_ui.h @@ -692,7 +692,7 @@ void meow_sheet_free(meow_sheet *s); /* §9 应用日志(统一日志 API,M2.51 最小可用版) */ /* ============================================================ */ /* app 只需一行 meow_log();SDK 管「写哪/怎么写/过滤/降级/上限」: - * - 路径:/apps//logs/<启动时间>_.log + * - 路径:/<启动时间>_.log(MEOW_LOG_DIR 已含包名分层 logs/<包名>) * (目录不存在 mkdir -p,按 app 分目录),每次启动=新文件,同一次启动内 O_APPEND 追加; * - 级别过滤:lvl < meow_log_get_level() 丢弃;默认 MEOW_LOG_INFO; * - 格式: [] message\n; diff --git a/meow_ui_gfx.c b/meow_ui_gfx.c index bc4c8ca..a25a41f 100644 --- a/meow_ui_gfx.c +++ b/meow_ui_gfx.c @@ -1135,6 +1135,7 @@ static void meow_gfx_load_multifont(void) int meow_ui_init(const meow_ui_opts *opts) { if (g_init_ok) return 0; + meow_log_install_exit_handler(); /* M2.78:SIGTERM/SIGINT 兜底写 exit: 日志 */ int fw = 0, fh = 0; if (opts) { fw = opts->width; fh = opts->height; } diff --git a/meow_ui_internal.h b/meow_ui_internal.h index 2d22645..241b396 100644 --- a/meow_ui_internal.h +++ b/meow_ui_internal.h @@ -102,6 +102,9 @@ void meow_gfx_mark_dirty(int x, int y, int w, int h); * 解除后由调用方一次 flush 原子上屏,避免覆盖层与 App on_tick 重绘同帧两刷频闪。 */ void meow_gfx_flush_hold(int on); +/* M2.78:安装 SIGTERM/SIGINT 退出日志兜底处理器(meow_ui_log.c;meow_ui_init 调用)。 */ +void meow_log_install_exit_handler(void); + /* 绘制期裁剪(MEOW_APP_SDK.md §3,2026-08-31):当前 clip 矩形内才写像素,默认全屏。 * meow_widget_draw(w) 画任何控件前 push 该控件矩形、画完 pop——任何控件(含 W_CUSTOM) * 画不出自身边界,根治自定义画布越界脏区。可嵌套(入栈/出栈,push 与当前 clip 求交)。 diff --git a/meow_ui_log.c b/meow_ui_log.c index d0981c4..73b4fc0 100644 --- a/meow_ui_log.c +++ b/meow_ui_log.c @@ -35,6 +35,7 @@ #include #include #include +#include #include /* 单行消息上限(超长截断) */ @@ -70,6 +71,8 @@ static int g_log_fallback = 0; /* 1=无卡/写失败,降级 stderr */ static int g_log_open_tried = 0; /* 是否已尝试开首个文件(只试一次,失败则降级) */ static unsigned long g_write_count = 0; /* 累计写入次数(周期总量清理节流) */ +static void log_open(void); /* 前向声明(log_sig_exit 在其定义之前使用) */ + /* 由 g_log_base + g_log_seq 重建当前文件路径(seq=0 无后缀,>0 追加 _)。 */ static void log_rebuild_file(void) { @@ -118,6 +121,28 @@ static void log_init(void) } } +/* 退出日志兜底(M2.78):App 被 watchdog 返回键 SIGTERM 时走默认终止,跳过正常 + * 路径的 meow_log("exit"),日志只剩 start。SDK 在 meow_ui_init 安装本处理器: + * SIGTERM/SIGINT → 直接 write 一条 exit:(绕过 stdio 缓冲)→ exit(0)(干净码)。 + * App 自装处理器(如 hello 画 BYE)会覆盖本处理器,其 exit(0) 路径不受影响。 */ +static void log_sig_exit(int sig) +{ + if (!g_log_open_tried) { g_log_open_tried = 1; log_open(); } + if (g_log_fd >= 0) { + char line[128]; + int n = snprintf(line, sizeof line, "%llu [%s] INFO exit:%s\n", + (unsigned long long)meow_ui_time_ms(), g_app_id, + sig == SIGTERM ? "sigterm" : "sigint"); + if (n > 0) { ssize_t w = write(g_log_fd, line, (size_t)n); (void)w; } + } + exit(0); +} +void meow_log_install_exit_handler(void) +{ + signal(SIGTERM, log_sig_exit); + signal(SIGINT, log_sig_exit); +} + /* mkdir -p:逐分量 mkdir(已存在 EEXIST 视为成功)。返回 0=成功,-1=失败。 */ static int log_mkdir_p(const char *path) {