[PATCH xlib] Add support for a display-specific error handler

Uli Schlachter psychon at znc.in
Thu Nov 19 07:58:19 PST 2015


Am 16.11.2015 um 21:57 schrieb Jasper St. Pierre:
> Now do this:
> 
> static void Foo()
> {
>     Request1();
>     Request2();
> }
> 
> static void Bar()
> {
>     Request1();
>     Request3();
> }
> 
> static void Thing(int x)
> {
>     SetErrorHandler();
>     if (x == 0)
>         Foo();
>     else
>         Bar();
>     UnsetErrorHandlerAndCheck();
> }
> 
> We have a similar codepath in our driver and this is where I gave up
> and started on the Xlib solution.

I agree that this gets a little more complicated, but ok:

struct pending_checked_requests {
  struct pending_checked_requests *next;
 xcb_void_request_t request;
};

static void add_checked(struct pending_checked_requests **pend,
xcb_void_request_t request)
{
  struct pending_checked_requests *n = malloc(sizeof(*n));
  n->request = request;
  n->next = *pend;
  *pend = n;
}

static int check_errors(struct pending_checked_requests *pend)
{
  int result = 0;
  while (pend) {
    if (xcb_request_check(pend->request)) {
       free error;
       result = 1;
    }
    struct pending_checked_requests *last = pend;
    pend = pend->next;
    free(last);
  }
  return result;
}

static void Bar(struct pcq **pend)
{
  add_checked(pend, Request1());
  add_checked(pend, Request2());
}

static int Thing(int x)
{
  struct pending_checked_requests *pend = NULL;
  if (x == 0)
    Bar(&pend);
  return check_errors(pend);
}

(And if (which I guess) the frequent malloc()s are a problem, then add something
more sophisticated where you e.g. have space for 20 requests in each such
structure and use stack space for the 50 first requests.)

> On Mon, Nov 16, 2015 at 12:39 PM, Uli Schlachter <psychon at znc.in> wrote:
>> Am 16.11.2015 um 18:06 schrieb Jasper St. Pierre:
>> [...]
>>> We currently use a behavior like:
>>>
>>>     SetErrorHandler();
>>>     Request1();
>>>     Request2();
>>>     Request3();
>>>     if (UnsetErrorHandlerAndCheck())
>>>         goto error;
>>>
>>> UnsetErrorHandlerAndCheck will XSync, and look at any newly incoming
>>> errors, check their serials so that they match up, and if they are
>>> inside those bounds, we return the error to the user and return that
>>> no error happened. Fairly standard trick.
>>>
>>> With xcb, I can do:
>>>
>>>     if (check_request(request_1_checked(), &err) {
>>>         free(err);
>>>         goto error;
>>>     }
>>>     if (check_request(request_2_checked(), &err) {
>>>         free(err);
>>>         goto error;
>>>     }
>>>     if (check_request(request_3_checked(), &err) {
>>>         free(err);
>>>         goto error;
>>>     }
>>>
>>> So that's clearly unusable.
>>
>> Well, why?
>>
>> How about this version:
>>
>> xcb_void_cookie_t cookies[3];
>>
>> cookies[0] = request_1_checked();
>> cookies[1] = request_2_checked();
>> cookies[2] = request_3_checked();
>>
>> bool had_error = false;
>> for (int i = 0; i < 3; i++) {
>>   xcb_generic_error_t *err = xcb_request_check(c, cookies[i]);
>>   had_error |= err != NULL;
>>   free(NULL);
>> }
>>
>> This only syncs once during the first call to xcb_request_check() and afterwards
>> it's done. This even improves parallelism, because you do not have to
>> XLockDisplay() to lock out other threads (which also means that "just a range of
>> sequence numbers" isn't enough and an array is needed).
>>
>> You could even generalize this with some helper functions to make it nicer,
>> similar to your SetErrorHandler() and UnsetErrorHandlerAndCheck() above.
>>
>> Uli
>>
>> [...]
>>> The Display-specific error handler solves my needs here by giving me a
>>> callback to that above model that's locked to that local section that
>>> works well from a library -- this code runs in a different thread, and
>>> we had issues where we overwrite another thread's error handler (in my
>>> case, the two threads were using different Displays, as they should).
>>>
>>> On Sun, Nov 15, 2015 at 11:56 PM, Keith Packard <keithp at keithp.com> wrote:
>>>> "Jasper St. Pierre" <jstpierre at mecheye.net> writes:
>>>>
>>>>> Writing error-safe code that uses Xlib is too obnoxious, and using XCB
>>>>> is tedious and not performant, as we can't catch events on a giant
>>>>> stream -- we have to check every operation manually.
>>>>
>>>> You get errors returned in the event stream; is there something fancier
>>>> you'd like from xcb to make it faster?
>>>>
>>>> --
>>>> -keith
>>
>> --
>> "Every once in a while, declare peace. It confuses the hell out of your enemies"
>>  - 79th Rule of Acquisition
>> _______________________________________________
>> xorg-devel at lists.x.org: X.Org development
>> Archives: http://lists.x.org/archives/xorg-devel
>> Info: http://lists.x.org/mailman/listinfo/xorg-devel
> 
> 
> 


-- 
Who needs a ~/.signature anyway?


More information about the xorg-devel mailing list