根因(真机日志 19000100_000000_7534.log):meow_ui_time_ms() 在设备上返回坏值——
低 32 位是「开机秒数×1000」(无毫秒),高 32 位每次调用随机(REPORT §42)。
旧守卫 `!g_home_thr_on && (!g_offline_retry_ms || now - g_offline_retry_ms >= 30000)`
因此恒真:worker 一收工,下一个 tick 立刻再重试;真机 74s 内 10 次
(间隔 5-7s 只是失败请求本身的连接超时)。第二条链是 else 分支清零重试时刻,
online/offline 一抖动就再试。
修复:
- 新增 app/logic/retry_ctl.{h,c}:节奏闸只做差值,时钟由调用方给可信单调钟
(home.c 改传 core 的 ncm_monotonic_ms());回退不下溢(重定基准、不重试);
busy 单飞;在线/离线抖动不重置基准;首次进离线立即探测一次,之后严格 ≥30s。
- home_tick 不再使用入参 now(真机坏值无效化);新增 home_retry_reset()。
- 静默重试不再走完整 home_reload:新增 home_reload_ex(silent) 不预读盘
(旧实现每轮在 UI 线程同步读 playlists.bin)、home_apply_ex(keep_scroll)
保留滚动位置、worker 记 g_home_changed 决定是否需要重绘——旧实现每轮
home_apply() 复位滚动+整帧重绘,是「歌单列表滑动特别卡」的直接来源。
- worker 线程 pthread_detach(旧代码每轮泄漏线程栈)。
31 lines
1.0 KiB
C
31 lines
1.0 KiB
C
/* logic/retry_ctl.c — 见 retry_ctl.h 头注释(M10 离线重试节奏闸)。 */
|
|
#include "retry_ctl.h"
|
|
|
|
void ncm_retry_ctl_init(ncm_retry_ctl *c)
|
|
{
|
|
if (!c) return;
|
|
c->last_ms = 0;
|
|
c->have_last = 0;
|
|
}
|
|
|
|
int ncm_retry_ctl_poll(ncm_retry_ctl *c, int offline, int busy, int64_t now_ms,
|
|
int64_t interval_ms)
|
|
{
|
|
if (!c || interval_ms <= 0) return 0;
|
|
if (!offline) return 0; /* 在线:不动基准 —— 抖动不得加速重试 */
|
|
if (busy) return 0; /* 单飞:上一个 worker 还在跑 */
|
|
|
|
if (!c->have_last) { /* 首次进离线:立即探测一次 */
|
|
c->have_last = 1;
|
|
c->last_ms = now_ms;
|
|
return 1;
|
|
}
|
|
if (now_ms < c->last_ms) { /* 时钟回退/异常:绝不让差值下溢成「巨大已超时」 */
|
|
c->last_ms = now_ms; /* 重定基准 → 仍需重新等满 interval */
|
|
return 0;
|
|
}
|
|
if (now_ms - c->last_ms < interval_ms) return 0;
|
|
c->last_ms = now_ms;
|
|
return 1;
|
|
}
|