mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-02 03:52:49 -05:00
Ignore X11 BadMatch errors during cut buffer setup.
This is quite a pain, since it involves inventing an entire new piece of infrastructure to install a custom Xlib error handler and give it a queue of things to do. But it fixes a bug in which Unix pterm/PuTTY crash out at startup if one of the root window's CUT_BUFFERn properties contains something of a type other than STRING - in particular, UTF8_STRING is not unheard-of. For example, run xprop -root -format CUT_BUFFER3 8u -set CUT_BUFFER3 "thingy" and then pterm without this fix would have crashed.
This commit is contained in:
88
unix/x11misc.c
Normal file
88
unix/x11misc.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* x11misc.c: miscellaneous stuff for dealing directly with X servers.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "putty.h"
|
||||
|
||||
#ifndef NOT_X_WINDOWS
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "x11misc.h"
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Error handling mechanism which permits us to ignore specific X11
|
||||
* errors from particular requests. We maintain a list of upcoming
|
||||
* potential error events that we want to not treat as fatal errors.
|
||||
*/
|
||||
|
||||
static int (*orig_x11_error_handler)(Display *thisdisp, XErrorEvent *err);
|
||||
|
||||
struct x11_err_to_ignore {
|
||||
Display *display;
|
||||
unsigned char error_code;
|
||||
unsigned long serial;
|
||||
};
|
||||
|
||||
struct x11_err_to_ignore *errs;
|
||||
|
||||
int nerrs, errsize;
|
||||
|
||||
static int x11_error_handler(Display *thisdisp, XErrorEvent *err)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nerrs; i++) {
|
||||
if (thisdisp == errs[i].display &&
|
||||
err->serial == errs[i].serial &&
|
||||
err->error_code == errs[i].error_code) {
|
||||
/* Ok, this is an error we're happy to ignore */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (*orig_x11_error_handler)(thisdisp, err);
|
||||
}
|
||||
|
||||
void x11_ignore_error(Display *disp, unsigned char errcode)
|
||||
{
|
||||
/*
|
||||
* Install our error handler, if we haven't already.
|
||||
*/
|
||||
if (!orig_x11_error_handler)
|
||||
orig_x11_error_handler = XSetErrorHandler(x11_error_handler);
|
||||
|
||||
/*
|
||||
* This is as good a moment as any to winnow the ignore list based
|
||||
* on requests we know to have been processed.
|
||||
*/
|
||||
{
|
||||
unsigned long last = LastKnownRequestProcessed(disp);
|
||||
int i, j;
|
||||
for (i = j = 0; i < nerrs; i++) {
|
||||
if (errs[i].display == disp && errs[i].serial <= last)
|
||||
continue;
|
||||
errs[j++] = errs[i];
|
||||
}
|
||||
nerrs = j;
|
||||
}
|
||||
|
||||
if (nerrs >= errsize) {
|
||||
errsize = nerrs * 5 / 4 + 16;
|
||||
errs = sresize(errs, errsize, struct x11_err_to_ignore);
|
||||
}
|
||||
errs[nerrs].display = disp;
|
||||
errs[nerrs].error_code = errcode;
|
||||
errs[nerrs].serial = NextRequest(disp);
|
||||
nerrs++;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user