While I was using st, my terminal suddenly crashed. Looking at the
command output, the cause was the following error message:

    X Error of failed request:  BadLength (poly request too large or
internal Xlib length error)
      Major opcode of failed request:  139 (RENDER)
      Minor opcode of failed request:  20 (RenderAddGlyphs)
      Serial number of failed request:  4087
      Current serial number in output stream:  4349

and subsequently it would exit with status code 1.

Using XSynchronize, I traced the error to come to the exact same
conclusion, in the drawing subroutine the RenderAddGlyphs was throwing
an error on an emoji.

I tested with other terminals, and urxvt showed me a "tofu", meaning
that my unicode fonts weren't rendering appropriately, and alacritty
renders nothing, which st does as well (with this patch). As a result,
I thought that a good compromise would be to at least treat this error
as non-fatal. This error handler will presumably catch other errors,
however, and I'm not sure if that's something to be worried about
because of my lack of experience with Xorg. However, having your main
terminal exit upon seeing a single character is much worse.

Thank you,
Ashkan Kiani
From 2ada33947649c0e15f22b7976a8fc8ba25bb3946 Mon Sep 17 00:00:00 2001
From: Ashkan Kiani <ashkan@zephyr>
Date: Sat, 16 Mar 2019 08:51:23 -0700
Subject: [PATCH] Add an X error handler

This prevents non-fatal errors such as the RenderAddGlyphs error thrown
when arriving at a unicode symbol (such as an emoji) which can't be
correctly rendered from exiting the program and rendering st unusable.

An example of the previous error message for such an error:

```
X Error of failed request:  BadLength (poly request too large or internal Xlib length error)
  Major opcode of failed request:  139 (RENDER)
  Minor opcode of failed request:  20 (RenderAddGlyphs)
  Serial number of failed request:  4087
  Current serial number in output stream:  4349
```

which would then be followed by exit(1).

An error message is provided which mirrors the original, sans names for
the opcodes.

```
XErrorEvent: BadLength (poly request too large or internal Xlib length error)
  Major opcode of failed request: 139
  Minor opcode of failed request: 20
  Serial number of failed request: 4044
```
---
 x.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/x.c b/x.c
index 5828a3b..5fa6d0d 100644
--- a/x.c
+++ b/x.c
@@ -1792,6 +1792,18 @@ resize(XEvent *e)
 	cresize(e->xconfigure.width, e->xconfigure.height);
 }
 
+int
+xevent_error_handler(Display* display, XErrorEvent* event) {
+  char buf[256];
+  XGetErrorText(display, event->error_code, buf, sizeof(buf));
+  fprintf(stderr,
+          "XErrorEvent: %s\n"
+          "  Major opcode of failed request: %d\n"
+          "  Minor opcode of failed request: %d\n"
+          "  Serial number of failed request: %d\n",
+          buf, event->request_code, event->minor_code, event->serial);
+}
+
 void
 run(void)
 {
@@ -1803,6 +1815,8 @@ run(void)
 	struct timespec drawtimeout, *tv = NULL, now, last, lastblink;
 	long deltatime;
 
+  XSetErrorHandler(xevent_error_handler);
+
 	/* Waiting for window mapping */
 	do {
 		XNextEvent(xw.dpy, &ev);
-- 
2.21.0

Reply via email to