[iOS][4.5.94] PAGImageView setHidden: 经 Task::wait 重入 flush 导致主线程卡死(Fatal App Hang)
I maintainer di solito rispondono entro 1 giorno
@leiyue123 ci sta già lavorando.
Dal 26/10/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
【版本信息】
- libpag 4.5.94,iOS 原生,CocoaPods 集成。
- 真实线上 Sentry 样本报告为
Fatal App Hang Fully Blocked,主线程阻塞至少 2000 ms;示例系统版本为 iOS 27.0.1。 - 下文关于 4.5.98 / main 的内容仅为源码对照,尚未在 4.5.98 上完成同场景复现或验证。
【实际情况】
一个已经播放的 PAGImageView 在列表状态更新时从可见变为隐藏,主线程调用 setHidden:YES 后发生卡死。采样堆栈显示:setHidden: 经 PAGAnimator::setDuration、extractAndWaitTask、tgfx::Task::wait,在同一个主线程栈内进入了 flush,最终停在 imageViewLock 对应的 mutex 获取处。
资源由本地 Bundle 加载,并非网络 URL,因此这个调用点不涉及弱网下载。
【预期表现】
在主线程隐藏正在播放的 PAGImageView,不应触发持锁状态下的同步 flush 重入,也不应造成长期主线程阻塞。
【真实堆栈】
以下保留 Sentry 样本的原始帧顺序和 SDK 源文件行号;未符号化的系统帧不猜测函数名。业务帧、应用名称、路径、地址、用户/设备标识以及内部 Sentry 链接均已移除。
#00 [unsymbolicated system frame]
#01 [unsymbolicated system frame]
#02 [unsymbolicated system frame]
#03 [unsymbolicated system frame]
#04 std::__1::lock_guard<T>::lock_guard[abi:nqe210106]
lock_guard.h:32
#05 std::__1::lock_guard<T>::lock_guard[abi:nqe210106]
lock_guard.h:31
#06 -[PAGImageView flush]
PAGImageView.mm:703
#07 pag::AnimatorListener::onAnimationUpdate
PAGAnimator.mm:121
#08 pag::PAGAnimator::onFlush
PAGAnimator.cpp:336
#09 pag::PAGAnimator::flushAsync::lambda::operator()
PAGAnimator.cpp:247
#10 std::__1::__invoke[abi:nqe210106]<T>
invoke.h:87
#11 std::__1::__invoke_void_return_wrapper<T>::__call[abi:nqe210106]<T>
invoke.h:342
#12 std::__1::__invoke_r[abi:nqe210106]<T>
invoke.h:348
#13 std::__1::__function::__func<T>::operator()
function.h:174
#14 tgfx::Task::wait
Task.cpp:80
#15 pag::PAGAnimator::extractAndWaitTask
PAGAnimator.cpp:232
#16 pag::PAGAnimator::setDuration
PAGAnimator.cpp:139
#17 -[PAGImageView setHidden:]
PAGImageView.mm:501
... application and unrelated frames omitted ...
【源码推断,待维护者确认】
PAGImageView::setHidden:持有非递归imageViewLock后调用checkVisible,隐藏时会调用setDuration(0)。- 4.5.94 的
extractAndWaitTask调用pendingTask->wait(500)。真实堆栈显示wait内部进入了动画 flush,而PAGImageView::flush会再次获取imageViewLock。这与同线程重复获取非递归锁相符,但单次采样不能独立证明全部锁归属或唯一根因。 - #3407 已将
setBounds:/setFrame:的 animator update 移到锁外;当前setHidden:/setAlpha:仍有持锁调用checkVisible的路径。 - #3554 为等待任务增加了 500 ms 超时,但如果
wait内同步执行的任务本身进入阻塞,是否能受该超时保护,需要确认。 - #3730 / 4.5.98 已调整异步调度,并在
extractAndWaitTask中增加 pending task cancellation 等处理。请确认该修改是否已经消除本 Issue 的确切重入链路。另一个需要核对的情形是:后台flush持有视图锁时,主线程直接等待imageViewLock,该等待是否仍可能无界。
【希望确认】
- 这条
setHidden -> setDuration -> Task::wait -> flush -> mutex链路是否属于已知问题? - 4.5.98 的 #3730 是否已修复该精确链路,还是仍需要把 animator 操作移出
imageViewLock? - 对
setHidden:/setAlpha:与后台 flush 竞争视图锁的情形,官方是否有推荐修复或可回移到 4.5.94 的补丁?
相关:#3407、#3554、#3730。这里报告的是 iOS 隐藏路径上的锁重入/等待问题,不是网络下载或解码器销毁 UAF。
【附件】
下图根据同一条真实 Sentry 事件的 SDK 堆栈脱敏重绘,便于阅读;不是 Sentry 页面原始截图。
- Lingua principale
- HTML
- Stelle
- 5.8k
- Fork
- 533
- Merge medio
- 3g 1h
- PR unite (30g)
- 28
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di Tencent/libpag
-
【Bug】HarmonyOS @tencent/libpag 4.4.25:远程 PAG URL 磁盘缓存不一致时,JPAGDiskCache.ReadFile 内 std::stoull 抛未捕获 C++ 异常导致 SIGABRTForse già presa @leiyue123 l’ha presa 3 giorni fa. Aperta
Tencent/libpag#3827 · 2 commenti · 2 assegnatari ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 15/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 18/100
I maintainer di solito rispondono entro 1 giorno
-
在ae2024里卡顿,在预览里闪烁Forse già presa @CodeJhF l’ha presa 20 giorni fa. Aperta
Tencent/libpag#3789 · 2 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
[iOS][4.5.98] HardwareDecoder 析构时 EXC_BAD_ACCESS,调用来自 VideoReader::destroyVideoDecoderForse già presa @CodeJhF l’ha presa 7 giorni fa. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 42/100
Tencent/libpag#3780 · 9 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno