一个多月没写blog,郁闷了…

X11的xcb库(1.7版)在不知道神马情况下会卡死

操作系统: opensuse 11.4 x86 语言: Qt 4.8.4,vdpau + Nv卡

症状: 在多线程下,调用vdpau_create_decoder会卡住

堆栈:

#0  0xffffe424 in __kernel_vsyscall ()
#1  0xb43dc03e in __poll (fds=0xa5d15798, nfds=1, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:87
#2  0xb1cc63f0 in _xcb_conn_wait (c=0x80f0b58, cond=0xa5d157f0, vector=0x0, count=0x0) at xcb_conn.c:313
#3  0xb1cc7d4f in xcb_wait_for_reply (c=0x80f0b58, request=13576, e=0xa5d1587c) at xcb_in.c:379
#4  0xb4213f92 in _XReply (dpy=0x80ffdb0, rep=0xa5d158bc, extra=0, discard=1) at xcb_io.c:533
#5  0xb0698032 in ?? () from /usr/lib/vdpau/libvdpau_nvidia.so.1
#6  0xb061715b in ?? () from /usr/lib/vdpau/libvdpau_nvidia.so.1
#7  0xb06174b7 in ?? () from /usr/lib/vdpau/libvdpau_nvidia.so.1
#8  0xb064dddb in ?? () from /usr/lib/vdpau/libvdpau_nvidia.so.1
#9  0xb067dbef in ?? () from /usr/lib/vdpau/libvdpau_nvidia.so.1
#10 0xb063b645 in ?? () from /usr/lib/vdpau/libvdpau_nvidia.so.1
#11 0xb061a423 in ?? () from /usr/lib/vdpau/libvdpau_nvidia.so.1
#12 0x0806d123 in mx::create_decoder (vdp=0x81f37f0, w=1920, h=1080, decoder=0x8235810) at ../../src/disp/xde_res_vdpau.cpp:79

最初,我猜是这个bug的原因

(Thread hangs in xcb_wait_for_reply() if another thread calls xcb_poll_for_event())[https://bugs.freedesktop.org/show_bug.cgi?id=40372]

看着bug的意思,是不正确的使用xcb库,但,我XXX, 那是驱动调用的,我哪知道呢…

按部就班修改了一下,测试,继续死… 我XXXX!!

好吧,换驱动

换最新的310系列,依然死,我XXXXXX

看来是bug,但怎么解决呢?

还是回到堆栈去, 卡死在xcb_wait_for_reply方法上,而这个方法有这样一句

378         while(!poll_for_reply(c, request, &ret, e)) {
379             if(!_xcb_conn_wait(c, &cond, 0, 0)) {
380                 break;
381             }
382             count ++; // 所以我加上下面几个逻辑,强制break,看看死不死
383             if ( count > 1000 ) {
384                 printf("Loop more than 1000 times, break");
385                 break;
386             }
387         }

结果,还是死….

看来要釜底抽薪啦,从最底层的api给跳出来

从第1帧来灭掉它

#1  0xb43dc03e in __poll (fds=0xa5d15798, nfds=1, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:87

这一帧调用linux标准的poll方法,但timeout传入的是-1,即永久等待.

反正不知道神马原因,就是没等到触发条件,卡住了, SO,妹的,改成1秒吧!!

代码如下:

312 #if USE_POLL
313         ret = poll(&fd, 1, 1000);
314 #else
315         ret = select(c->fd + 1, &rfds, &wfds, 0, 0);
316 #endif

编译,重启, 测试, 竟然好了,我XXX,但为什么呢? 不知道呢… 反正没再死了…

mark一下gdb常用命令

gdb -p $pid        直接attach到正在运行的程序中

set height 0       显示时,不分页
info threads       显示所有线程
thread 3           切换到3号线程
bt                 显示当前线程的堆栈
f 2                调到第二帧
c                  继续运行
Ctrl+C             中断运行,进行gdb交互模式
info locals        打印全部本地变量
print fd           打印名为fd的变量的值


blog comments powered by Disqus

Published

2013-05-23

Categories


Tags

Fork me on GitHub