Случайные зависания libx11
Мое приложение случайно зависает при вызове функций libX11. Например: звонок XGetClassHint
, XGetWindowProperty
или же XListInputDevices
иногда не возвращаются.
Например, вот обратная трассировка при звонке XGetClassHint
#0 0xb70a762c in poll () from /lib/libc.so.6
#1 0xb6f980f0 in _xcb_conn_wait (c=0x9d66a20, cond=0xbf98c600, vector=0x0, count=0x0) at ../../src/xcb_conn.c:316
#2 0xb6f9a7e1 in xcb_wait_for_reply (c=0x9d66a20, request=178, e=0xbf98c68c) at ../../src/xcb_in.c:395
#3 0xb7597746 in _XReply (dpy=0x9d660d8, rep=0xbf98c6f0, extra=0, discard=0) at ../../src/xcb_io.c:462
#4 0xb75750a0 in XGetWindowProperty (dpy=0x9d660d8, w=31457802, property=67, offset=0, length=8192, delete=0, req_type=31, actual_type=0xbf98c78c, actual_format=0xbf98c788, nitems=0xbf98c784, bytesafter=0xbf98c780, prop=0xbf98c77c) at ../../src/GetProp.c:70
#5 0xb7573f51 in XGetClassHint (dpy=0x9d660d8, w=31457802, classhint=0xbf98c83c) at ../../src/GetHints.c:312
#6 0x080ccfac in WindowManager::get_class (this=0x8144460, window=@0xbf98c814, clase=0xbf98c83c) at src/WindowManager.cpp:1334
Я проследил сообщения X11 между моим приложением и сервером, и я получил ответ на запрос GetProperty WM_CLASS
:
001:<:00b2: 24: Request(20): GetProperty delete=false(0x00) window=0x01e0020a property=0x43("WM_CLASS") type=0x1f("STRING") long-offset=0x00000000 long-length=0x00002000
001:>:00b2:52: Reply to GetProperty: type=0x1f("STRING") bytes-after=0x00000000 data='Navigator\000Iceweasel\000'
Мое приложение однопоточное, и я вижу, что оно все еще получает и обрабатывает сообщения X11 с сервера, но похоже, что оно никогда не возвращается из XGetClassHint
потому что по какой-то причине не обработал ответ GetProperty.
Операционная система, которую я использую, является стандартной версией Debian, и соответствующие пакеты:
ii libx11-6 2:1.3.3-4+squeeze1 X11 client-side library
ii libx11-6-dbg 2:1.3.3-4+squeeze1 X11 client-side library (debug package)
ii libx11-data 2:1.3.3-4+squeeze1 X11 client-side library
ii libx11-dev 2:1.3.3-4+squeeze1 X11 client-side library (development headers)
ii libx11-xcb1 2:1.3.3-4+squeeze1 Xlib/XCB interface library
ii libx11-xcb1-dbg 2:1.3.3-4+squeeze1 Xlib/XCB interface library (debug package)
ii libxcb1 1.6-1+squeeze1 X C Binding
ii libxcb1-dbg 1.6-1+squeeze1 X C Binding, debugging symbols
ii libxcb1-dev 1.6-1+squeeze1 X C Binding, development files
Есть идеи, что может быть причиной этого?
Спасибо!
Обновить
После некоторой дополнительной отладки кажется, что эта проблема возникала, когда программа обрабатывала SIGCHLD. В обработчике сигналов я просто писал в канал, чтобы уведомить основной поток, но не делал никаких операций с libX11. Но в итоге удаление обработчика сигнала заставило проблему исчезнуть. Имеет ли это смысл? или я могу ожидать, что эта проблема появится снова в будущем?
еще раз спасибо
1 ответ
Это может быть либо потому, что вы делаете что-то в SIGCHLD
обработчик (или как результат), который вы не должны или менее вероятно, потому что Xcb не обрабатывает EINTR
ошибка правильно.
Я думаю, что SIGCHLD
доставляется в поток (который я назову потоком жнеца), пока он находится в середине вызова Xcb. Затем обработчик выполняет запись в канал, который блокируется, поскольку буфер канала заполнен. Нить жнеца теперь держит замок Xcb, ожидая, когда труба истечет. Основной поток, который должен читать канал, затем вызывает Xcb, который пытается получить блокировку, которую удерживает поток жнеца. Поскольку нить жнеца заблокирована, ожидая, пока основной поток прочитает трубу, а основная нить заблокирована, ожидая, пока нить жнеца освободит блокировку Xcb, вы получите тупик.