зеркало из https://github.com/github/putty.git
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:
Родитель
ca68700570
Коммит
36ddc57084
2
Recipe
2
Recipe
|
@ -217,7 +217,7 @@ GUITERM = TERMINAL window windlg winctrls sizetip winucs winprint
|
|||
|
||||
# Same thing on Unix.
|
||||
UXTERM = TERMINAL uxcfg sercfg uxucs uxprint timing callback miscucs
|
||||
GTKTERM = UXTERM gtkwin gtkcfg gtkdlg gtkfont gtkcols gtkmisc xkeysym
|
||||
GTKTERM = UXTERM gtkwin gtkcfg gtkdlg gtkfont gtkcols gtkmisc xkeysym x11misc
|
||||
OSXTERM = UXTERM osxwin osxdlg osxctrls
|
||||
|
||||
# Non-SSH back ends (putty, puttytel, plink).
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
#include <X11/Xatom.h>
|
||||
#endif
|
||||
|
||||
#include "x11misc.h"
|
||||
|
||||
#define CAT2(x,y) x ## y
|
||||
#define CAT(x,y) CAT2(x,y)
|
||||
#define ASSERT(x) enum {CAT(assertion_,__LINE__) = 1 / (x)}
|
||||
|
@ -2961,20 +2963,28 @@ void init_clipboard(struct gui_data *inst)
|
|||
*/
|
||||
unsigned char empty[] = "";
|
||||
Display *disp = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
|
||||
x11_ignore_error(disp, BadMatch);
|
||||
XChangeProperty(disp, GDK_ROOT_WINDOW(),
|
||||
XA_CUT_BUFFER0, XA_STRING, 8, PropModeAppend, empty, 0);
|
||||
x11_ignore_error(disp, BadMatch);
|
||||
XChangeProperty(disp, GDK_ROOT_WINDOW(),
|
||||
XA_CUT_BUFFER1, XA_STRING, 8, PropModeAppend, empty, 0);
|
||||
x11_ignore_error(disp, BadMatch);
|
||||
XChangeProperty(disp, GDK_ROOT_WINDOW(),
|
||||
XA_CUT_BUFFER2, XA_STRING, 8, PropModeAppend, empty, 0);
|
||||
x11_ignore_error(disp, BadMatch);
|
||||
XChangeProperty(disp, GDK_ROOT_WINDOW(),
|
||||
XA_CUT_BUFFER3, XA_STRING, 8, PropModeAppend, empty, 0);
|
||||
x11_ignore_error(disp, BadMatch);
|
||||
XChangeProperty(disp, GDK_ROOT_WINDOW(),
|
||||
XA_CUT_BUFFER4, XA_STRING, 8, PropModeAppend, empty, 0);
|
||||
x11_ignore_error(disp, BadMatch);
|
||||
XChangeProperty(disp, GDK_ROOT_WINDOW(),
|
||||
XA_CUT_BUFFER5, XA_STRING, 8, PropModeAppend, empty, 0);
|
||||
x11_ignore_error(disp, BadMatch);
|
||||
XChangeProperty(disp, GDK_ROOT_WINDOW(),
|
||||
XA_CUT_BUFFER6, XA_STRING, 8, PropModeAppend, empty, 0);
|
||||
x11_ignore_error(disp, BadMatch);
|
||||
XChangeProperty(disp, GDK_ROOT_WINDOW(),
|
||||
XA_CUT_BUFFER7, XA_STRING, 8, PropModeAppend, empty, 0);
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* x11misc.h: header file for functions that need to refer to Xlib
|
||||
* data types. Has to be separate from unix.h so that we can include
|
||||
* it only after including the X headers, which in turn has to be done
|
||||
* after putty.h has told us whether NOT_X_WINDOWS is defined.
|
||||
*/
|
||||
|
||||
#ifndef NOT_X_WINDOWS
|
||||
|
||||
/*
|
||||
* x11misc.c.
|
||||
*/
|
||||
void x11_ignore_error(Display *disp, unsigned char errcode);
|
||||
|
||||
#endif
|
Загрузка…
Ссылка в новой задаче