- app.json 新字段 background/background_audio 解析入 struct app/meow_acct 注册表
- meow_ipc.h:MSG_REGISTER(m_register_t)/SERVICE_OK(m_ack_t.status=pid)/SERVICE_STOP/
MSG_SYS(m_sys_t, SHUTDOWN=1/SVC_DEAD=2) 负载结构落地
- 新模块 meow_bgplay.c/h(自包含+ops 注入,仿 meow_media,宿主可单测):
· 后台播放保活——声明 background_audio 且媒体会话 PLAYING 的 App nav-exit 不终止,
进程+音频流保留;UI 冻结走 §10.5 /tmp/meow_notif_active SDK present 自抑(非字面
SIGSTOP:冻结同进程播放线程断供 PCM,§10.5 真机实证);点图标/媒体卡片回前台=
原进程恢复(chain/picker 忽略),停播后再退出=真退 SIGTERM
· 无头后台服务——MSG_REGISTER spawn/stop/reap + 退避重启 1/2/4/10s cap +
max_restart 熔断(清该 App 通知 + 注册连接广播 MSG_SYS{SVC_DEAD},重注册复位)
· 卡拔例外(卡上二进制后台 App/服务仍 SIGTERM 防 SIGBUS)、崩溃照收、
关机前 meow_bgplay_kill_all 有界回收(含 MSG_SYS{SHUTDOWN} 广播)
- util.c:MSG_REGISTER/MSG_SERVICE_STOP 分发(权限/声明校验链)+ ipc_conn_alive 连接
存活查询 + meow_ipc_process 末尾挂 meow_bg_housekeep(drain/reap/退避 tick)
- app_launcher.c:launch_app_chain 入口 resume(bg_take 原进程回前台)+ nav-exit
保活分支 + 转后台出口(杀看门狗/写自抑标记/复位顶条,跳过退出尾)+ 冷启动自动
拉起静态 keepalive(mode=0) 服务(exec 路径约定=App 同目录 <svc> 文件)
- main_menu.c:应用列表「·后台」标注(宫格/列表,1s tick 按 change_seq 刷新)+
两条退出尾 kill_all + unlink NOTIF_ACTIVE
- 宿主单测 test_bgplay.c 50 项全过(真 fork 子进程走状态机 + 假时钟退避熔断);
test_media/test_notif_panel/test_notif_tf/test_vol_ramp_jack 回归全过;
zig-mipsel-cc -Wall -Wextra 0 warning。launcher md5=c07d011c0769fca14d3bfb752d735463
510 lines
15 KiB
C
510 lines
15 KiB
C
/* meow_bgplay.c — M4 后台播放保活 + 无头后台服务运行时表(见 meow_bgplay.h 头注释)。 */
|
||
#include "meow_bgplay.h"
|
||
|
||
#include <stdarg.h>
|
||
#include <stdio.h>
|
||
#include <signal.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <time.h>
|
||
#include <unistd.h>
|
||
#include <sys/wait.h>
|
||
#include <fcntl.h>
|
||
|
||
static meow_bgplay_ops g_ops;
|
||
static meow_bg_entry_t g_bg[MEOW_BG_MAX];
|
||
static meow_svc_rt_t g_svc[MEOW_SVC_RT_MAX];
|
||
static uint32_t g_change_seq;
|
||
|
||
static const uint32_t k_backoff[] = {
|
||
MEOW_SVC_BACKOFF_1, MEOW_SVC_BACKOFF_2, MEOW_SVC_BACKOFF_4, MEOW_SVC_BACKOFF_10
|
||
};
|
||
#define BACKOFF_STEPS ((int)(sizeof(k_backoff) / sizeof(k_backoff[0])))
|
||
|
||
/* SIGTERM 后 SIGKILL 兜底宽限(ms) */
|
||
#define TERM_GRACE_MS 500u
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
static void bg_log(const char *fmt, ...)
|
||
{
|
||
va_list ap;
|
||
char buf[384];
|
||
|
||
if (!g_ops.log) return;
|
||
va_start(ap, fmt);
|
||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||
va_end(ap);
|
||
g_ops.log("%s", buf);
|
||
}
|
||
|
||
static uint64_t bg_now_ms(void)
|
||
{
|
||
struct timespec ts;
|
||
|
||
if (g_ops.now_ms) return g_ops.now_ms();
|
||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||
return (uint64_t)ts.tv_sec * 1000u + (uint64_t)ts.tv_nsec / 1000000u;
|
||
}
|
||
|
||
static int bg_card_present(void)
|
||
{
|
||
return g_ops.card_present ? g_ops.card_present() : 1;
|
||
}
|
||
|
||
void meow_bgplay_init(const meow_bgplay_ops *ops)
|
||
{
|
||
memset(&g_ops, 0, sizeof(g_ops));
|
||
memset(g_bg, 0, sizeof(g_bg));
|
||
memset(g_svc, 0, sizeof(g_svc));
|
||
g_change_seq = 0;
|
||
if (ops) g_ops = *ops;
|
||
}
|
||
|
||
/* ================= 后台播放保活 ================= */
|
||
|
||
int meow_bg_should_keep(int bg_audio_declared, int media_playing)
|
||
{
|
||
return bg_audio_declared && media_playing;
|
||
}
|
||
|
||
static meow_bg_entry_t *bg_find(const char *app_id)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < MEOW_BG_MAX; i++)
|
||
if (g_bg[i].used && strcmp(g_bg[i].app_id, app_id) == 0)
|
||
return &g_bg[i];
|
||
return NULL;
|
||
}
|
||
|
||
int meow_bg_add(const char *app_id, pid_t pid, int out_fd, int on_card)
|
||
{
|
||
int i;
|
||
|
||
if (!app_id || !app_id[0] || pid <= 0) return MEOW_ERR_INVAL;
|
||
if (bg_find(app_id)) return MEOW_ERR_EXISTS;
|
||
for (i = 0; i < MEOW_BG_MAX; i++) {
|
||
if (!g_bg[i].used) {
|
||
meow_bg_entry_t *e = &g_bg[i];
|
||
|
||
memset(e, 0, sizeof(*e));
|
||
e->used = 1;
|
||
snprintf(e->app_id, sizeof(e->app_id), "%s", app_id);
|
||
e->pid = pid;
|
||
e->out_fd = out_fd;
|
||
e->on_card = on_card;
|
||
g_change_seq++;
|
||
bg_log("[bgplay] 转后台保活: %s pid=%d on_card=%d", app_id, (int)pid, on_card);
|
||
return 0;
|
||
}
|
||
}
|
||
return MEOW_ERR_NOMEM;
|
||
}
|
||
|
||
int meow_bg_take(const char *app_id, int *out_fd, pid_t *pid)
|
||
{
|
||
meow_bg_entry_t *e;
|
||
|
||
if (!app_id || !app_id[0]) return -1;
|
||
e = bg_find(app_id);
|
||
if (!e) return -1;
|
||
if (out_fd) *out_fd = e->out_fd;
|
||
if (pid) *pid = e->pid;
|
||
bg_log("[bgplay] 回前台: %s pid=%d", app_id, (int)e->pid);
|
||
memset(e, 0, sizeof(*e));
|
||
g_change_seq++;
|
||
return 0;
|
||
}
|
||
|
||
int meow_bg_is_backgrounded(const char *app_id)
|
||
{
|
||
return app_id && app_id[0] && bg_find(app_id) != NULL;
|
||
}
|
||
|
||
int meow_bg_count(void)
|
||
{
|
||
int i, n = 0;
|
||
|
||
for (i = 0; i < MEOW_BG_MAX; i++)
|
||
if (g_bg[i].used) n++;
|
||
return n;
|
||
}
|
||
|
||
const meow_bg_entry_t *meow_bg_at(int i)
|
||
{
|
||
if (i < 0 || i >= MEOW_BG_MAX || !g_bg[i].used) return NULL;
|
||
return &g_bg[i];
|
||
}
|
||
|
||
uint32_t meow_bgplay_change_seq(void)
|
||
{
|
||
return g_change_seq;
|
||
}
|
||
|
||
void meow_bg_tick(void)
|
||
{
|
||
uint64_t now = bg_now_ms();
|
||
int i;
|
||
|
||
for (i = 0; i < MEOW_BG_MAX; i++) {
|
||
meow_bg_entry_t *e = &g_bg[i];
|
||
int st;
|
||
pid_t r;
|
||
|
||
if (!e->used) continue;
|
||
|
||
/* 卡拔例外:二进制在卡上 → SIGTERM(防 SIGBUS),500ms 未死 SIGKILL */
|
||
if (e->on_card && !bg_card_present()) {
|
||
if (e->term_at_ms == 0) {
|
||
bg_log("[bgplay] 卡拔出,终止卡上后台 App: %s pid=%d",
|
||
e->app_id, (int)e->pid);
|
||
kill(e->pid, SIGTERM);
|
||
e->term_at_ms = now;
|
||
} else if (now - e->term_at_ms >= TERM_GRACE_MS) {
|
||
kill(e->pid, SIGKILL);
|
||
e->term_at_ms = now; /* 500ms 节流重复 SIGKILL 直至 reap */
|
||
}
|
||
}
|
||
|
||
r = waitpid(e->pid, &st, WNOHANG);
|
||
if (r == e->pid) {
|
||
char id[MEOW_APP_ID_MAX];
|
||
pid_t pid = e->pid;
|
||
|
||
snprintf(id, sizeof(id), "%s", e->app_id);
|
||
memset(e, 0, sizeof(*e));
|
||
g_change_seq++;
|
||
bg_log("[bgplay] 后台 App 退出: %s pid=%d status=0x%x", id, (int)pid, st);
|
||
if (g_ops.on_bg_dead) g_ops.on_bg_dead(id, pid, st);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* ================= 无头后台服务 ================= */
|
||
|
||
static meow_svc_rt_t *svc_find_mut(const char *app_id, const char *svc)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < MEOW_SVC_RT_MAX; i++)
|
||
if (g_svc[i].used && strcmp(g_svc[i].app_id, app_id) == 0 &&
|
||
strcmp(g_svc[i].svc, svc) == 0)
|
||
return &g_svc[i];
|
||
return NULL;
|
||
}
|
||
|
||
const meow_svc_rt_t *meow_svc_find(const char *app_id, const char *svc)
|
||
{
|
||
if (!app_id || !svc) return NULL;
|
||
return svc_find_mut(app_id, svc);
|
||
}
|
||
|
||
/* spawn 服务子进程:stdio→/dev/null,env={PATH,HOME,MEOW_SERVICE[,MEOW_LOG_DIR/MEOW_LOG_APP]}。
|
||
* 父进程返回 pid;子进程不返回(execve 或 _exit(127))。 */
|
||
static pid_t svc_spawn(meow_svc_rt_t *s)
|
||
{
|
||
char env_service[32];
|
||
char env_logdir[160];
|
||
char env_logapp[64];
|
||
char *envp[6];
|
||
int n = 0;
|
||
pid_t pid;
|
||
|
||
envp[n++] = (char *)"PATH=/usr/bin:/bin:/usr/sbin:/sbin";
|
||
envp[n++] = (char *)"HOME=/root";
|
||
snprintf(env_service, sizeof(env_service), "MEOW_SERVICE=%s", s->svc);
|
||
envp[n++] = env_service;
|
||
if (g_ops.log_dir && g_ops.log_dir[0]) {
|
||
snprintf(env_logdir, sizeof(env_logdir), "MEOW_LOG_DIR=%s", g_ops.log_dir);
|
||
envp[n++] = env_logdir;
|
||
snprintf(env_logapp, sizeof(env_logapp), "MEOW_LOG_APP=%s", s->app_id);
|
||
envp[n++] = env_logapp;
|
||
}
|
||
envp[n] = NULL;
|
||
|
||
pid = fork();
|
||
if (pid != 0) return pid; /* 父:pid 或 -1 */
|
||
|
||
/* 子进程:脱离终端会话,stdio 全部重定向 /dev/null(无头服务) */
|
||
setsid();
|
||
{
|
||
int dn = open("/dev/null", O_RDWR);
|
||
if (dn >= 0) {
|
||
dup2(dn, STDIN_FILENO);
|
||
dup2(dn, STDOUT_FILENO);
|
||
dup2(dn, STDERR_FILENO);
|
||
if (dn > STDERR_FILENO) close(dn);
|
||
}
|
||
}
|
||
{
|
||
char *argv[2];
|
||
|
||
argv[0] = s->exec;
|
||
argv[1] = NULL;
|
||
execve(s->exec, argv, envp);
|
||
}
|
||
_exit(127); /* exec 失败:父进程 tick 回收后按退避/熔断处理 */
|
||
}
|
||
|
||
int meow_svc_register(const char *app_id, const char *svc, const char *exec,
|
||
int restart, int max_restart, int window_ms,
|
||
int on_card, int reg_fd)
|
||
{
|
||
meow_svc_rt_t *s;
|
||
pid_t pid;
|
||
int i;
|
||
|
||
if (!app_id || !app_id[0] || !svc || !svc[0] || !exec || !exec[0])
|
||
return MEOW_ERR_INVAL;
|
||
if (access(exec, X_OK) != 0) return MEOW_ERR_NOENT;
|
||
|
||
s = svc_find_mut(app_id, svc);
|
||
if (s) {
|
||
if (s->pid > 0) return MEOW_ERR_EXISTS;
|
||
if (!s->circuit) return MEOW_ERR_EXISTS; /* 退避排程中也视为在册 */
|
||
/* 熔断槽重注册:复位熔断,重新武装 */
|
||
bg_log("[bgplay] 服务熔断复位重注册: %s/%s", app_id, svc);
|
||
s->circuit = 0;
|
||
s->stopping = 0;
|
||
s->restart_count = 0;
|
||
s->window_start_ms = bg_now_ms();
|
||
s->next_retry_ms = 0;
|
||
s->reg_fd = reg_fd;
|
||
s->on_card = on_card;
|
||
} else {
|
||
for (i = 0; i < MEOW_SVC_RT_MAX; i++)
|
||
if (!g_svc[i].used) break;
|
||
if (i >= MEOW_SVC_RT_MAX) return MEOW_ERR_NOMEM;
|
||
s = &g_svc[i];
|
||
memset(s, 0, sizeof(*s));
|
||
s->used = 1;
|
||
snprintf(s->app_id, sizeof(s->app_id), "%s", app_id);
|
||
snprintf(s->svc, sizeof(s->svc), "%s", svc);
|
||
snprintf(s->exec, sizeof(s->exec), "%s", exec);
|
||
s->restart = restart;
|
||
s->max_restart = max_restart;
|
||
s->window_ms = window_ms;
|
||
s->on_card = on_card;
|
||
s->reg_fd = reg_fd;
|
||
s->window_start_ms = bg_now_ms();
|
||
}
|
||
|
||
pid = svc_spawn(s);
|
||
if (pid < 0) {
|
||
if (s->pid == 0 && s->restart_count == 0 && !s->circuit)
|
||
memset(s, 0, sizeof(*s)); /* 新槽首次 fork 即败:不留尸槽 */
|
||
return MEOW_ERR_IO;
|
||
}
|
||
s->pid = pid;
|
||
s->term_at_ms = 0;
|
||
bg_log("[bgplay] 服务拉起: %s/%s pid=%d restart=%d max=%d",
|
||
app_id, svc, (int)pid, restart, max_restart);
|
||
return (int)pid;
|
||
}
|
||
|
||
int meow_svc_stop(const char *app_id, const char *svc)
|
||
{
|
||
meow_svc_rt_t *s;
|
||
|
||
if (!app_id || !svc) return MEOW_ERR_INVAL;
|
||
s = svc_find_mut(app_id, svc);
|
||
if (!s) return MEOW_ERR_NOENT;
|
||
bg_log("[bgplay] 服务停止: %s/%s pid=%d", app_id, svc, (int)s->pid);
|
||
if (s->pid > 0) {
|
||
s->stopping = 1;
|
||
kill(s->pid, SIGTERM);
|
||
s->term_at_ms = bg_now_ms();
|
||
} else {
|
||
/* 未在跑(退避中/熔断):直接清槽 */
|
||
if (g_ops.on_svc_dead) g_ops.on_svc_dead(s->app_id, s->svc);
|
||
memset(s, 0, sizeof(*s));
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/* 服务死亡后的退避/熔断判定。返回 1=已排程重启;0=槽已清或熔断。 */
|
||
static int svc_on_exit(meow_svc_rt_t *s, int st)
|
||
{
|
||
uint64_t now = bg_now_ms();
|
||
|
||
bg_log("[bgplay] 服务退出: %s/%s pid=%d status=0x%x stopping=%d",
|
||
s->app_id, s->svc, (int)s->pid, st, s->stopping);
|
||
s->pid = 0;
|
||
|
||
if (s->stopping || !s->restart) {
|
||
if (g_ops.on_svc_dead) g_ops.on_svc_dead(s->app_id, s->svc);
|
||
memset(s, 0, sizeof(*s));
|
||
return 0;
|
||
}
|
||
|
||
/* 滑窗:超窗复位计数 */
|
||
if (s->window_ms > 0 && now - s->window_start_ms >= (uint64_t)s->window_ms) {
|
||
s->restart_count = 0;
|
||
s->window_start_ms = now;
|
||
}
|
||
s->restart_count++;
|
||
|
||
if (s->max_restart > 0 && s->restart_count > s->max_restart) {
|
||
/* 熔断:清通知 + 广播 MSG_SYS{SVC_DEAD},槽保留待重注册复位 */
|
||
m_sys_t m;
|
||
|
||
s->circuit = 1;
|
||
s->next_retry_ms = 0;
|
||
bg_log("[bgplay] 服务熔断: %s/%s 窗口内重启 %d 次超 max=%d",
|
||
s->app_id, s->svc, s->restart_count, s->max_restart);
|
||
if (g_ops.notif_clear_app)
|
||
g_ops.notif_clear_app(s->app_id);
|
||
if (g_ops.send_frame && s->reg_fd >= 0) {
|
||
memset(&m, 0, sizeof(m));
|
||
m.event = MEOW_SYS_SVC_DEAD;
|
||
snprintf(m.app_id, sizeof(m.app_id), "%s", s->app_id);
|
||
snprintf(m.svc, sizeof(m.svc), "%s", s->svc);
|
||
g_ops.send_frame(s->reg_fd, MSG_SYS, 0, &m, sizeof(m));
|
||
}
|
||
if (g_ops.on_svc_dead) g_ops.on_svc_dead(s->app_id, s->svc);
|
||
return 0;
|
||
}
|
||
|
||
{
|
||
int step = s->restart_count - 1;
|
||
uint32_t dly;
|
||
|
||
if (step >= BACKOFF_STEPS) step = BACKOFF_STEPS - 1;
|
||
dly = k_backoff[step];
|
||
s->next_retry_ms = now + dly;
|
||
bg_log("[bgplay] 服务退避重启: %s/%s 第 %d 次,%ums 后拉起",
|
||
s->app_id, s->svc, s->restart_count, (unsigned)dly);
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
void meow_svc_tick(void)
|
||
{
|
||
uint64_t now = bg_now_ms();
|
||
int i;
|
||
|
||
for (i = 0; i < MEOW_SVC_RT_MAX; i++) {
|
||
meow_svc_rt_t *s = &g_svc[i];
|
||
|
||
if (!s->used) continue;
|
||
|
||
/* 卡拔例外:exec 在卡上 → SIGTERM + stopping=1(不重启防空转死循环) */
|
||
if (s->on_card && s->pid > 0 && !bg_card_present() && !s->stopping) {
|
||
bg_log("[bgplay] 卡拔出,终止卡上服务: %s/%s pid=%d",
|
||
s->app_id, s->svc, (int)s->pid);
|
||
s->stopping = 1;
|
||
kill(s->pid, SIGTERM);
|
||
s->term_at_ms = now;
|
||
}
|
||
/* SIGTERM 宽限超时 → SIGKILL */
|
||
if (s->stopping && s->pid > 0 && s->term_at_ms &&
|
||
now - s->term_at_ms >= TERM_GRACE_MS) {
|
||
kill(s->pid, SIGKILL);
|
||
s->term_at_ms = now;
|
||
}
|
||
|
||
if (s->pid > 0) {
|
||
int st;
|
||
pid_t r = waitpid(s->pid, &st, WNOHANG);
|
||
|
||
if (r == s->pid) svc_on_exit(s, st);
|
||
continue;
|
||
}
|
||
|
||
/* 退避到点 → 重新拉起 */
|
||
if (!s->circuit && !s->stopping && s->restart &&
|
||
s->next_retry_ms && now >= s->next_retry_ms) {
|
||
pid_t pid = svc_spawn(s);
|
||
|
||
s->next_retry_ms = 0;
|
||
if (pid > 0) {
|
||
s->pid = pid;
|
||
bg_log("[bgplay] 服务重启: %s/%s pid=%d(第 %d 次)",
|
||
s->app_id, s->svc, (int)pid, s->restart_count);
|
||
} else {
|
||
/* fork 失败:压到下一档重试 */
|
||
s->next_retry_ms = now + k_backoff[BACKOFF_STEPS - 1];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* ================= 关机前回收 ================= */
|
||
|
||
void meow_bgplay_kill_all(void)
|
||
{
|
||
uint64_t deadline;
|
||
int i;
|
||
|
||
/* best-effort 广播 SHUTDOWN */
|
||
if (g_ops.send_frame) {
|
||
m_sys_t m;
|
||
|
||
memset(&m, 0, sizeof(m));
|
||
m.event = MEOW_SYS_SHUTDOWN;
|
||
for (i = 0; i < MEOW_SVC_RT_MAX; i++)
|
||
if (g_svc[i].used && g_svc[i].reg_fd >= 0)
|
||
g_ops.send_frame(g_svc[i].reg_fd, MSG_SYS, 0, &m, sizeof(m));
|
||
}
|
||
|
||
for (i = 0; i < MEOW_BG_MAX; i++)
|
||
if (g_bg[i].used && g_bg[i].pid > 0) kill(g_bg[i].pid, SIGTERM);
|
||
for (i = 0; i < MEOW_SVC_RT_MAX; i++)
|
||
if (g_svc[i].used && g_svc[i].pid > 0) kill(g_svc[i].pid, SIGTERM);
|
||
|
||
/* 有界等 1s(轮询 reap,期间 tick 语义不在——直接 waitpid) */
|
||
deadline = bg_now_ms() + 1000u;
|
||
while (bg_now_ms() < deadline) {
|
||
int alive = 0;
|
||
|
||
for (i = 0; i < MEOW_BG_MAX; i++) {
|
||
if (!g_bg[i].used) continue;
|
||
if (waitpid(g_bg[i].pid, NULL, WNOHANG) == g_bg[i].pid)
|
||
memset(&g_bg[i], 0, sizeof(g_bg[i]));
|
||
else
|
||
alive++;
|
||
}
|
||
for (i = 0; i < MEOW_SVC_RT_MAX; i++) {
|
||
if (!g_svc[i].used) continue;
|
||
if (waitpid(g_svc[i].pid, NULL, WNOHANG) == g_svc[i].pid)
|
||
memset(&g_svc[i], 0, sizeof(g_svc[i]));
|
||
else
|
||
alive++;
|
||
}
|
||
if (!alive) break;
|
||
usleep(50 * 1000);
|
||
}
|
||
|
||
/* 兜底 SIGKILL + 有界 reap(waitpid 阻塞上限由 SIGKILL 必死保证) */
|
||
for (i = 0; i < MEOW_BG_MAX; i++)
|
||
if (g_bg[i].used) {
|
||
kill(g_bg[i].pid, SIGKILL);
|
||
waitpid(g_bg[i].pid, NULL, 0);
|
||
memset(&g_bg[i], 0, sizeof(g_bg[i]));
|
||
}
|
||
for (i = 0; i < MEOW_SVC_RT_MAX; i++)
|
||
if (g_svc[i].used) {
|
||
kill(g_svc[i].pid, SIGKILL);
|
||
waitpid(g_svc[i].pid, NULL, 0);
|
||
memset(&g_svc[i], 0, sizeof(g_svc[i]));
|
||
}
|
||
g_change_seq++;
|
||
bg_log("[bgplay] kill_all 完成(关机/退出回收)");
|
||
}
|
||
|
||
void meow_bgplay_dump(const char *prefix)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < MEOW_BG_MAX; i++)
|
||
if (g_bg[i].used)
|
||
bg_log("%s bg[%d] %s pid=%d on_card=%d", prefix, i,
|
||
g_bg[i].app_id, (int)g_bg[i].pid, g_bg[i].on_card);
|
||
for (i = 0; i < MEOW_SVC_RT_MAX; i++)
|
||
if (g_svc[i].used)
|
||
bg_log("%s svc[%d] %s/%s pid=%d restart=%d count=%d circuit=%d",
|
||
prefix, i, g_svc[i].app_id, g_svc[i].svc, (int)g_svc[i].pid,
|
||
g_svc[i].restart, g_svc[i].restart_count, g_svc[i].circuit);
|
||
}
|