根因(真机日志 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(旧代码每轮泄漏线程栈)。
43 lines
2.4 KiB
C
43 lines
2.4 KiB
C
/* logic/retry_ctl.h — 离线自动重试节奏闸(M10:断网重试风暴的修复点)。
|
||
*
|
||
* 背景(真机 19000100_000000_7534.log + launcher meow_20261105_122541.log):
|
||
* M9 的 30s 守卫写成 `if (!thr_on && (!last || now - last >= 30000))`,节奏完全依赖
|
||
* meow_ui_time_ms() 的 64 位差值。真机实测该值「低 32 位 = 整秒×1000(无毫秒)、高 32 位是垃圾」
|
||
* (见 REPORT §42),于是 now-last 几乎恒为巨大正数 → 每个 UI tick 都判「该重试」,
|
||
* 断网时把「30s 一次」退化成「每个 tick 一次」的重试风暴。
|
||
*
|
||
* 本模块把节奏判定收敛成三条硬约束(纯逻辑、零依赖,宿主编译可直接驱动):
|
||
* 1) 时钟由调用方供给**可信单调钟**(home.c 传 core 的 ncm_monotonic_ms(),不再用 SDK 的
|
||
* meow_ui_time_ms());本模块只做差值,不取时间。
|
||
* 2) 时钟回退(now < last)绝不下溢成「巨大已超时」:按「刚试过」处理并重定基准,
|
||
* 下一次尝试仍需重新等满 interval。
|
||
* 3) 单飞:busy(上一个 worker 未收工)期间任何时钟跳变都不发新尝试。
|
||
* 在线/离线抖动不重置基准 —— 抖动无法加速重试(旧实现 else 分支清零 g_offline_retry_ms,
|
||
* 状态一抖就立刻再试,是风暴的第二条触发链)。
|
||
*/
|
||
#ifndef NCM_RETRY_CTL_H
|
||
#define NCM_RETRY_CTL_H
|
||
|
||
#include <stdint.h>
|
||
|
||
typedef struct {
|
||
int64_t last_ms; /* 上次发起尝试的单调毫秒时刻(have_last=0 时无意义) */
|
||
int have_last; /* 1=至少尝试过一次 */
|
||
} ncm_retry_ctl;
|
||
|
||
void ncm_retry_ctl_init(ncm_retry_ctl *c);
|
||
|
||
/* 每个 UI tick 调一次。返回 1=现在应当发起一次重试(内部已记账:调用方随即起 worker)。
|
||
* offline=当前是否离线;busy=是否已有 worker 在跑(单飞);now_ms=单调毫秒;
|
||
* interval_ms=两次尝试的最小间隔(M10 定 30000)。
|
||
*
|
||
* 语义:
|
||
* - offline=0:返回 0,且**不动**基准(在线期间与状态抖动都不重置节奏)。
|
||
* - busy=1:返回 0。
|
||
* - 首次观察到离线:返回 1(进离线先立即探测一次,恢复后由会话门切回在线)。
|
||
* - 之后:仅当 now-last >= interval 才返回 1;now<last(时钟回退)→ 重置基准、返回 0。 */
|
||
int ncm_retry_ctl_poll(ncm_retry_ctl *c, int offline, int busy, int64_t now_ms,
|
||
int64_t interval_ms);
|
||
|
||
#endif /* NCM_RETRY_CTL_H */
|