我们正在开发一个复杂的应用程序,该应用程序由定制的.jar文件中的linux二进制文件与java jni调用(来自linux二进制文件中创建的JVM)集成在一起。所有的gui工作都是由Java部分实现和完成的。每次必须更改gui属性或必须重绘gui时,都可以通过jni调用JVM来完成。完整的显示/ gui会以JVM / java能够处理的速度重新绘制(或刷新)。迭代和频繁地完成它,每秒几乎没有回声或数千次迭代。经过一段确切的时间后,应用程序被exit(1)终止,而我用gdb捕获了该应用程序,以便从_XIOError()进行调用。可以在或多或少的确切时间段(例如,在x86双核2.5GHz上经过15小时后。如果我使用速度较慢的计算机,则它的使用寿命会更长,就像它与cpu / gpu速度成正比。可以得出结论,xorg的某些部分用光了某些资源或类似资源。这是我的回溯:#0 0xb7fe1424 in __kernel_vsyscall ()#1 0xb7c50941 in raise () from /lib/i386-linux-gnu/i686/cmov/libc.so.6#2 0xb7c53d72 in abort () from /lib/i386-linux-gnu/i686/cmov/libc.so.6#3 0xb7fdc69d in exit () from /temp/bin/liboverrides.so#4 0xa0005c80 in _XIOError () from /usr/lib/i386-linux-gnu/libX11.so.6#5 0xa0003afe in _XReply () from /usr/lib/i386-linux-gnu/libX11.so.6#6 0x9fffee7b in XSync () from /usr/lib/i386-linux-gnu/libX11.so.6#7 0xa01232b8 in X11SD_GetSharedImage () from /usr/lib/jvm/jre1.8.0_20/lib/i386/libawt_xawt.so#8 0xa012529e in X11SD_GetRasInfo () from /usr/lib/jvm/jre1.8.0_20/lib/i386/libawt_xawt.so#9 0xa01aac3d in Java_sun_java2d_loops_ScaledBlit_Scale () from /usr/lib/jvm/jre1.8.0_20/lib/i386/libawt.so我在liboverrides.so中进行了自己的exit()调用,并与LD_PRELOAD结合使用,以在exit() / SIGABRT的帮助下捕获gdb中的abort()调用。在对libX11和libxcb进行一些调试之后,我注意到_XReply()收到了NULL响应(来自xcb_wait_for_reply()的响应),从而导致调用_XIOError()和exit(1)。我对xcb_wait_for_reply()函数中的libxcb进行了更深入的研究,我注意到它可以返回NULL应答的原因之一是当它检测到套接字连接断开或关闭时,这可能就是我的情况。出于测试目的,如果我更改xcb_io.c并忽略_XIOError(),则应用程序不再起作用。如果我在_XReply()中重复请求,则每次都会失败,即在每个xcb_wait_for_reply()上获得NULL响应。因此,我的问题将是为什么这样的不受控制的应用终止而发生_XReply()-> XIOError()-> exit(1)一些解决方法。如我上面所写,要使此问题重复出现,我必须等待15个小时,但目前我的调试时间很短,无法找到问题/终止的原因。我们还尝试重新组织处理gui / display刷新的Java部分,但问题并未解决。SW的一些事实:-Java jre 1.8.0_20,即使使用Java 7也可以重复出现此问题-libX11.so 1.5.0-libxcb.so 1.8.1-Debian Wheezy-内核3.2.0 最佳答案 这可能是libX11中有关xcb_wait_for_reply使用的请求编号的处理的已知问题。在libxcb v1.5代码之后的某个时刻,引入了在内部各处使用64位序列号的代码,并且在进入仍采用32位序列号的那些公共API时添加了逻辑以扩大序列号。这是来自submitted libxcb bug report的报价(实际电子邮件已删除):  我们有一个执行很多XDrawString和XDrawLine的应用程序。  几个小时后,XIOError退出了应用程序。    XIOError在文件xcb_io.c的libX11中调用,函数  _XReply。它没有收到来自xcb_wait_for_reply的响应。    libxcb 1.5没问题,libxcb 1.8.1没问题。均分libxcb指向  此提交:    提交ed37b087519ecb9e74412e4df8f8a217ab6d12a9作者:Jamey  夏普日期:2010年10月9日星期六17:13:45xcb_in: Use 64-bit sequence numbers internally everywhere.Widen sequence numbers on entry to those public APIs that still take32-bit sequence numbers.Signed-off-by: Jamey Sharp <[email protected]>    将其还原为1.8.1会有帮助。    添加跟踪到libxcb我发现最后一个请求号用于  xcb_wait_for_reply是这些:4294900463和4294965487(两次调用  _XReply函数的while循环),半秒后:63215  (然后调用XIOError)。 widen_request也是63215,我会  预期为63215 + 2 ^ 32。因此,似乎请求不是  正确加宽。    上面的提交还更改了poll_for_reply中的比较  XCB_SEQUENCE_COMPARE_32至XCB_SEQUENCE_COMPARE。也许正在扩大  永远无法正常工作,但从未被观察到,因为只有  比较低32位。重现问题这是提交的错误报告中的原始代码段,用于重现该问题: for(;;) { XDrawLine(dpy, w, gc, 10, 60, 180, 20); XFlush(dpy); }显然,这个问题可以用更简单的代码重现: for(;;) { XNoOp(dpy); }根据提交的libxcb错误报告,再现这些条件是必需的(假设再现代码在xdraw.c中):    libxcb> = 1.8(即包含提交ed37b08)  用32位编译:gcc -m32 -lX11 -o xdraw xdraw.c  序列计数器换行。  建议的补丁可以在libxcb 1.8.1之上应用的建议补丁是:diff --git a/src/xcb_io.c b/src/xcb_io.cindex 300ef57..8616dce 100644--- a/src/xcb_io.c+++ b/src/xcb_io.c@@ -454,7 +454,7 @@ void _XSend(Display *dpy, const char *data, long size) static const xReq dummy_request; static char const pad[3]; struct iovec vec[3];- uint64_t requests;+ unsigned long requests; _XExtension *ext; xcb_connection_t *c = dpy->xcb->connection; if(dpy->flags & XlibDisplayIOError)@@ -470,7 +470,7 @@ void _XSend(Display *dpy, const char *data, long size) if(dpy->xcb->event_owner != XlibOwnsEventQueue || dpy->async_handlers) { uint64_t sequence;- for(sequence = dpy->xcb->last_flushed + 1; sequence <= dpy->request; ++sequence)+ for(sequence = dpy->xcb->last_flushed + 1; (unsigned long) sequence <= dpy->request; ++sequence) append_pending_request(dpy, sequence); } requests = dpy->request - dpy->xcb->last_flushed;详细的技术说明Plase查找波纹管包含在detailed technical explanation by Jonas Petersen中(也包含在上述错误报告中):  你好    这是两个补丁。第一个修复了32位序列换行错误。  第二个补丁仅在另一个相关语句中添加了注释。    补丁包含一些细节。这是谁的全部故事  可能感兴趣:    Xlib(libx11)将使应用程序崩溃,并显示“致命IO错误11  (资源暂时不可用)”在4 294 967 296请求后  服务器。这就是Xlib内部32位序列换行的时间。    大多数应用程序可能很难达到这个数字,但是如果它们  这样做,他们就有机会死于神秘的死亡。例如  我正在处理的应用程序总是在20小时后崩溃  我开始做一些压力测试。它做一些密集的绘图  通过Xlib使用gktmm2,pixmap和gc绘图(每帧40帧)  全高清分辨率第二(在Ubuntu上)。做了一些优化  将宽限期延长到大约35小时,但仍然会崩溃。    然后是几周令人沮丧的挖掘和调试工作  意识到它不在我的应用程序中,也不在gtkmm,gtk或glib中  但这是自2006年10月6日以来存在的Xlib中的这个小错误  显然。    过了一段时间才发现数字0x100000000(2 ^ 32)具有  一些相关性。 (很多)后来证明,它可以与  仅Xlib,例如使用以下代码:    while(1){        XDrawPoint(display,drawable,gc,x,y);        XFlush(显示); }    可能需要一两个小时,但当达到42.94亿时  它将爆炸为“致命IO错误11”。    然后我了解到,即使Xlib使用内部32bit  在此过程中,它们(巧妙地)获得的序列号扩展为64位  这样32位序列可以自动换行,而不会中断  加宽了64位序列。显然这一定是有问题的  那。    如果无法获取_XReply(),则会发出致命IO错误  在应该有一个的地方回复,但是原因在_XSend()中更早  Xlib 32位序列号结束时。    问题是当它换成0时,'last_flushed'的值  仍将位于上限(例如0xffffffff)。有两个  在的位置  _XSend()(xcb_io.c)在此状态下失败,因为它们一直依赖那些连续的值,第一个位置是:    request = dpy-> request-dpy-> xcb-> last_flushed;    如果请求= 0x0并且last_flushed = 0xffffffff,它将分配  0xffffffff00000001发送到“ requests”,然后作为数字(金额)发送到XCB  的请求。这是主要的杀手。    第二个位置是这样的:    for(序列= dpy-> xcb-> last_flushed +1;序列请求;  \      ++序列)    如果请求= 0x0(小于last_flushed),则没有机会  曾经进入循环,因此一些请求被忽略。    解决方案是在这两个位置“解包” dpy-> request,然后  因此保留与last_flushed相关的序列。    uint64_t unwrapped_request =(((uint64_t)(dpy-> request       dpy-> xcb-> last_flushed) request;    它会创建一个临时的64位请求号,如果该请求号设置为8,  “请求”小于“ last_flushed”。然后在两个中使用  位置而不是dpy-> request。    我不确定使用该语句是否可能更有效  就位,而不是使用变量。    首先,require_socket()中还有另一行让我担心:    dpy-> xcb-> last_flushed = dpy-> request =已发送;    这是64位,32位,64位分配。它将截断“发送”到  将其设置为“ request”时为32位,然后分配  截断为(64位)'last_flushed'的值。但这似乎是事实。  我添加了一条注释,解释了下一次可怜的灵魂调试  顺序问题... :-)      乔纳斯      Jonas Petersen(2):xcb_io:修复Xlib 32位请求数字换行  xcb_io:添加注释以解释混合类型双重分配    src / xcb_io.c | 14 +++++++++++ ---更改了1个文件,插入了11个(+),  3次删除(-)    -  1.7.10.4祝好运!
09-29 22:21