<html>
    <head>
      <base href="https://bugs.freedesktop.org/" />
    </head>
    <body>
      <p>
        <div>
            <b><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Deadlock in _XReply when recursing through _XSeqSyncFunction"
   href="https://bugs.freedesktop.org/show_bug.cgi?id=59361#c4">Comment # 4</a>
              on <a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Deadlock in _XReply when recursing through _XSeqSyncFunction"
   href="https://bugs.freedesktop.org/show_bug.cgi?id=59361">bug 59361</a>
              from <span class="vcard"><a class="email" href="mailto:p.horrocks89@gmail.com" title="Peter Horrocks <p.horrocks89@gmail.com>"> <span class="fn">Peter Horrocks</span></a>
</span></b>
        <pre>It looks like commit 83e1ba59c48c79f8b0a7e7aa0b9c9cfd84fa403d introduced the
problem.

The commit unlocks the display when an application-defined error handler is
invoked, but re-locking the display requires re-syncing the sequence numbers
which requires a remote call.

The commit author couldn't remember why the display lock was held while the
error function was called - I guess the sequence number re-sync was the reason.

Reverting the commit fixes the problem.

In the meantime, an application can use this code to work around the problem -
it uses a custom extension error handler to cause XError to return before it
unlocks/locks the screen:

typedef Bool (*WireToErrorType)(Display*, XErrorEvent*, xError*);

const int NUM_HANDLERS = 256;
WireToErrorType __oldHandlers[NUM_HANDLERS] = {0};

Bool __xErrorHandler(
        Display*     display,
        XErrorEvent* event,
        xError*      error
        )
{
    // Call any previous handler first in case it needs to do real work.
    auto code = static_cast<int>(event->error_code);
    if(__oldHandlers[code] != NULL)
    {
        __oldHandlers[code](display, event, error);
    }

    // Always return false so the error does not get passed to the normal
    // application defined handler.
    return False;
}

void applyXDeadlockFix(Display* display)
{
    for(auto i = 0; i < NUM_HANDLERS; ++i)
    {
        XESetWireToError(display, i, &__xErrorHandler);
    }
}</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>