Android的BUG(二) - SurfaceTexture中的野指针
当初遇到这个bug,是不定期的低概率出现,最后找到一个比较容易重现的步骤:
启动系统
然后进google +
新建一个帐号(注意是新建一个帐号)
没几步就重启了
这个BUG,一开始追踪也是无头绪的,在这个bug出现时,系统的debuggerd还是有些问题,pt_regs设置的和内核对应不 上,tombstone的信息完全无用,core dump功能也是无法使用,唯一的线索就是一点点logcat的trace, trace如下:
D/OpenGLRenderer( 2021): Flushing caches (mode 1) D/OpenGLRenderer( 2021): Flushing caches (mode 0) D/OpenGLRenderer( 1986): Flushing caches (mode 1) W/SurfaceTexture( 1451): freeAllBuffersLocked called but mQueue is not empty D/OpenGLRenderer( 1986): Flushing caches (mode 0) F/libc ( 1451): Fatal signal 11 (SIGSEGV) at 0x00000024 (code=1) I/DEBUG ( 1449): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** I/DEBUG ( 1449): Build fingerprint: 'xxxx/IML74K/eng.freshui.20120213.154128:user/test-keys' I/DEBUG ( 1449): pid: 1451, tid: 1455 >>> /system/bin/surfaceflinger <<< I/DEBUG ( 1449): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000024
重现时的错误,基本上都是类似的trace。 从此入手开始查找。 Trace中的一句话:
W/SurfaceTexture( 1451): freeAllBuffersLocked called but mQueue is not empty
是最大的怀疑目标,基于捉虫的经验,先做假定,已经可以解释出错的原因和现象了:
- mQueue通常是被两个模块使用的,一个enqueue,一个dequeue
- 出错时,要将mQueue 给free掉,但mQueue不空,说明有人在用
- 如果不管这个警告,强行将mQueue给free掉,极有可能造成另外一个模块使用被free掉的内存而引起段错误
转回头看代码,SurfaceTexture.cpp, 查一下mQueue的使用地方,哪里有出现free buffer的时候,mQueue 不为空的可能? 排查一下,还真找到了,看下这个函数:
- status_t SurfaceTexture::setBufferCount(int bufferCount) {
- ST_LOGV("setBufferCount: count=%d", bufferCount);
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (bufferCount > NUM_BUFFER_SLOTS) {
- ST_LOGE("setBufferCount: bufferCount larger than slots available");
- return BAD_VALUE;
- }
- // Error out if the user has dequeued buffers
- for (int i=0 ; i<mBufferCount ; i++) {
- if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
- ST_LOGE("setBufferCount: client owns some buffers");
- return -EINVAL;
- }
- }
- const int minBufferSlots = mSynchronousMode ?
- MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
- if (bufferCount == 0) {
- mClientBufferCount = 0;
- bufferCount = (mServerBufferCount >= minBufferSlots) ?
- mServerBufferCount : minBufferSlots;
- return setBufferCountServerLocked(bufferCount);
- }
- if (bufferCount < minBufferSlots) {
- ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
- "minimum (%d)", bufferCount, minBufferSlots);
- return BAD_VALUE;
- }
- // here we're guaranteed that the client doesn't have dequeued buffers
- // and will release all of its buffer references.
- freeAllBuffersLocked();
- mBufferCount = bufferCount;
- mClientBufferCount = bufferCount;
- mCurrentTexture = INVALID_BUFFER_SLOT;
- mQueue.clear();
- mDequeueCondition.signal();
- return OK;
- }
找到问题后,在freeAllBuffersLocked()调用之前,将mQueue给抽干一下,等使用的client都用完了再free就好了。
修改之后,再也没有碰到此类错误了。
当然此问题的排查和解决过程没这么顺利,也是搞了好几天的。 解决方法和问题原因也就不细说了,碰到并准备捉这个虫的同学应该会看明白的。
呵呵,这又是可以归结为 多线程同步/状态机 的问题,基本上目前我在Android碰到的严重问题都是这类了
版权声明:本文为博主原创文章,未经博主允许不得转载。
分类:
android提高篇
, android相关问题处理
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
2014-10-31 Android RatingBar自定义替换系统图片
2014-10-31 Android 中文 API (40) —— RatingBar
2013-10-31 Android静态变量的生命周期