Случайные зависания 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. Но, в конце концов, удаление обработчика сигнала заставило проблему исчезнуть. Имеет ли это смысл? или я могу ожидать, что эта проблема появится снова в будущем?

Спасибо еще раз


person sgimeno    schedule 06.08.2014    source источник
comment
Можете ли вы построить на родной Xlib вместо XlibXcb?   -  person n. 1.8e9-where's-my-share m.    schedule 09.08.2014
comment
@н.м. Я не уверен, как это сделать с помощью пакетов Debian. Удаление libx11-xcb, вероятно, сработает, но мне нужна эта зависимость для других вещей, которые я использую.   -  person sgimeno    schedule 12.08.2014
comment
Я недостаточно знаком с XlibXcb, но я уверен, что вам не нужно ничего удалять. Вы просто связываете свое приложение с -lX11 вместо -lx11-xcb1 или чем-то еще. Это не обязательно сработает. Ну, я почти уверен, что это не сработает, но просто может сработать, поэтому я и спрашиваю.   -  person n. 1.8e9-where's-my-share m.    schedule 12.08.2014


Ответы (1)


Это может быть либо потому, что вы делаете что-то в обработчике SIGCHLD (или в результате), чего вы не должны делать, либо, что менее вероятно, потому что Xcb неправильно обрабатывает ошибку EINTR.

Я предполагаю, что SIGCHLD доставляется потоку (который я назову потоком жнеца), когда он находится в середине вызова Xcb. Затем обработчик записывает в канал, который блокируется, потому что буфер канала заполнен. Поток жнеца теперь удерживает блокировку Xcb, ожидая, пока труба опустеет. Основной поток, который должен читать канал, затем вызывает Xcb, который пытается получить блокировку, удерживаемую потоком-жнецом. Поскольку поток жнеца заблокирован, ожидая, пока основной поток прочитает канал, а основной поток заблокирован, ожидая, пока поток жнеца освободит блокировку Xcb, вы получите взаимоблокировку.

person Ross Ridge    schedule 12.08.2014
comment
Спасибо за ответ! Если я хорошо понимаю, что вы говорите, я думаю, что проблема не в этом. Я не вижу, чтобы основной поток был заблокирован (в смысле попытки получить блокировку, уже удерживаемую потоком жнеца). На самом деле основной поток успешно читает из канала и продолжает читать сообщения X11 с сервера, но он заблокирован, потому что по какой-то причине он пропускает правильный ответ на запрос, поэтому метод Xlib никогда не возвращает результат. - person sgimeno; 13.08.2014
comment
Я только что заметил, что вы сказали, что ваше приложение однопоточное, но в своем обновлении вы говорите, что обработчик SIGCHLD уведомляет основной поток, предполагая, что он работает в другом потоке. Создали ли вы еще один поток для обработки SIGCHLD (или для чего-либо еще) или ваше приложение действительно однопоточное? - person Ross Ridge; 13.08.2014
comment
Да, прости. Он однопоточный, и в обработчике SIGCHLD я пишу в неблокирующий сокет unix. Позже, когда обработчик сигнала выйдет из режима выбора, программа «проснется» и прочитает данные, отправленные обработчиком сигнала. Я надеюсь, что это имеет смысл для вас - person sgimeno; 13.08.2014