X11的xcb库卡死
一个多月没写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