Обработка ошибок в Xlib
Почему X-программа может упасть из-за ошибки в запросе, отправленном двадцать вызовов назад, и что с этим делают XSetErrorHandler и -sync.
Xlib буферизует запросы и не ждёт ответов без необходимости, поэтому когда сервер отклоняет один из них — BadWindow для уже уничтоженного окна, BadMatch для pixmap неверной глубины, BadAccess, BadAlloc, BadValue, — ошибка возвращается как событие, намного позже вызова, который её вызвал. Обработчик по умолчанию печатает «X Error of failed request» с кодом ошибки, опкодом (Major opcode 20 (X_GetProperty)), идентификатором ресурса и двумя серийными номерами, а затем завершает программу. Ключ — серийные номера: сравнив номер сбойного запроса с текущим, понимаешь, насколько ты отстал.
XSetErrorHandler подставляет собственный обработчик, и почти каждый оконный менеджер так делает: клиент может уничтожить своё окно между моментом, когда менеджер узнал о нём, и моментом, когда он начал действовать; эту гонку не выиграть, её можно только проигнорировать. XSetIOErrorHandler закрывает другой случай — обрыв соединения, из которого возврата нет. Для отладки XSynchronize или флаг Xt -sync заставляют каждый запрос ждать ответа, так что ошибка приходит в нужный вызов, а точка останова на _XError в gdb показывает где; цена — один обмен на запрос. XCB перестроил модель: ошибки приходят как ответ на вызвавший их запрос, их собирают через xcb_request_check или из очереди событий, и глобального обработчика, который можно забыть установить, нет.