Tratamento de erros da Xlib
Por que um programa X pode morrer por causa de um erro em uma requisição enviada vinte chamadas atrás, e o que XSetErrorHandler e -sync fazem a respeito.
A Xlib coloca as requisições em buffer e não espera por respostas a menos que seja obrigada, então, quando o servidor rejeita uma – BadWindow para uma janela que já foi destruída, BadMatch para um pixmap de profundidade errada, BadAccess, BadAlloc, BadValue –, o erro volta como um evento muito depois da chamada que o causou. O tratador padrão imprime "X Error of failed request" com o código do erro, o opcode (Major opcode 20 (X_GetProperty)), o ID do recurso e dois números de série, e então encerra o programa. Os números de série são a pista: o da requisição que falhou, comparado ao atual, mostra quanto você está atrasado.
XSetErrorHandler instala um tratador próprio, e quase todo gerenciador de janelas o faz, porque um cliente pode destruir sua janela entre o momento em que o gerenciador toma conhecimento dela e o momento em que age; essa corrida não tem como ser vencida, só ignorada. XSetIOErrorHandler cobre o outro caso, o de conexão rompida, do qual não há volta. Para depurar, XSynchronize ou a flag do Xt -sync faz cada requisição esperar pela resposta, de modo que o erro cai na chamada certa, e um breakpoint em _XError no gdb mostra onde; o preço é uma ida e volta por requisição. O XCB refez o modelo: os erros voltam como resposta à requisição que os causou, coletados com xcb_request_check ou da fila de eventos, e não existe tratador global que se possa esquecer de instalar.