X11_KeyRepeat crash

Hello list!

On X11, sometimes, when you move your mouse and release the keyboard
key at the same time, you get a SIGSERV crash. (see dumps and demo
program at the end)

I’ve “tracked” it down to the X11_KeyRepeat function in
SDL_x11events.c. The function looks for next X11 event in the queue and
compares it to the current one, working around keyboard auto-repeat
feature of X11.

The culprit is XPeekEvent, which either crashes itself, either
corrupts something, so next XNextEvent call crashes.

Now, as far as I can tell, SDL does everything correctly. So it might
be a bug in libX11 or my video driver.

However, some things are a bit weird. This never happens with SDL1.2,
altho I compared the code for X11_KeyRepeat and related and it looked
very very similar…

Additionally, something tells me this doesn’t happen for regular X11
programs, but I don’t have any proof for this yet, going to try it next.

Also, if I remove the SDL_Delay() call, the bug seems to be gone, so I
might be doing something wrong in the first place. Are SDL_Delay()
calls not considered good practice in SDL2 ?

I’d be very grateful if you guys would test this. If you’re not seeing
the crash, you can change the “2” in the following line to “10” or a
larger value, makes it easier to trigger:

src/video/x11/SDL_x11events.c:113
((peekevent.xkey.time-event->xkey.time) < 2)) {

You’re aiming to “inject” a MotionNotify event inbetween the
KeyRelease and the auto-repeated KeyPress. For me, it crashes reliably
when this happens.

(I use libX11 1.4.1 and nvidia-driver 295.49)

test program:

#include <SDL.h>

int main(int argc, char* argv[])
{
SDL_Window* window;
SDL_Renderer *renderer;

    SDL_Init(SDL_INIT_VIDEO);
    window = SDL_CreateWindow("X11_KeyPreat problem",
                    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                    512, 512,
                    SDL_WINDOW_SHOWN);
    renderer = SDL_CreateRenderer(window, -1, 0);	
    SDL_SetRenderDrawColor(renderer, 0xFF, 0, 0, 255);
    SDL_RenderClear(renderer);

    int done = 0;

    while (!done) {
        SDL_Event event;
        SDL_zero(event);
		while (SDL_PollEvent(&event)) {
			if (event.type == SDL_QUIT) done = 1;
		}
		SDL_RenderPresent(renderer);
		//SDL_Delay(10);
}

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;

}

gdb backtrace:

#0 0xb7fe1424 in __kernel_vsyscall ()
#1 0xb7d85451 in raise () from /lib/libc.so.6
#2 0xb7d86b92 in abort () from /lib/libc.so.6
#3 0xb7dc09f5 in ?? () from /lib/libc.so.6
#4 0xb7dc6861 in ?? () from /lib/libc.so.6
#5 0xb7dc966d in ?? () from /lib/libc.so.6
#6 0xb7dcb27c in malloc () from /lib/libc.so.6
#7 0xb7c3944c in _XStoreEventCookie () from /usr/lib/libX11.so.6
#8 0xb7c284bc in XPeekEvent () from /usr/lib/libX11.so.6
#9 0xb7fa46a5 in XPeekEvent (a=0x804e788, b=0xbfffeccc)
at …/src/video/x11/SDL_x11sym.h:94
#10 0xb7fb519b in X11_KeyRepeat (_this=0x804dd58)
at …/src/video/x11/SDL_x11events.c:110
#11 X11_DispatchEvent
(_this=0x804dd58)at …/src/video/x11/SDL_x11events.c:444
#12 X11_PumpEvents (_this=0x804dd58)
at …/src/video/x11/SDL_x11events.c:914
#13 0xb7f33c84 in SDL_PumpEvents () at …/src/events/SDL_events.c:309
#14 0xb7f341ba in SDL_WaitEventTimeout (event=0xbfffef90,timeout=0)
at …/src/events/SDL_events.c:342
#15 0xb7f34295 in SDL_PollEvent(event=0xbfffef90)
at …/src/events/SDL_events.c:324 #16 0x080488e8 in main (argc=1,
argv=0xbffff094) at event.c:22

Relevant valgrind output:

==32494== Invalid write of size 1
==32494== at 0x4027164: memcpy
==32494== by 0x486C3F4: ??? (in /usr/lib/libXi.so.6.1.0)
==32494== by 0x472E7C7:_XCopyEventCookie(in /usr/lib/libX11.so.6.3.0)
==32494== by 0x471E481: XPeekEvent (in /usr/lib/libX11.so.6.3.0)
==32494== by 0x40D06A4: XPeekEvent (SDL_x11sym.h:94)
==32494== by 0x40E119A: X11_PumpEvents (SDL_x11events.c:110)
==32494== by 0x405FC83: SDL_PumpEvents (SDL_events.c:309)
==32494== by 0x40601B9: SDL_WaitEventTimeout (SDL_events.c:342)
==32494== by 0x4060294: SDL_PollEvent (SDL_events.c:324)
==32494== by 0x80488E7: main(event.c:22)
==32494== Address 0x707f29b is 7 bytes after a block of size 60 alloc’d
==32494== at 0x402582E: malloc
==32494== by 0x486C341: ??? (in /usr/lib/libXi.so.6.1.0)
==32494== by 0x472E7C7:_XCopyEventCookie(in /usr/lib/libX11.so.6.3.0)
==32494== by 0x471E481: XPeekEvent (in /usr/lib/libX11.so.6.3.0)
==32494== by 0x40D06A4: XPeekEvent (SDL_x11sym.h:94)
==32494== by 0x40E119A: X11_PumpEvents (SDL_x11events.c:110)
==32494== by 0x405FC83: SDL_PumpEvents (SDL_events.c:309)
==32494== by 0x40601B9: SDL_WaitEventTimeout (SDL_events.c:342)
==32494== by 0x4060294: SDL_PollEvent (SDL_events.c:324)
==32494== by 0x80488E7: main(event.c:22)–
driedfruit

Same crash happens on debian squeeze, libx11 1.3.3, nvidia 275.09.

Commenting out the X11_KeyRepeat call “fixes” it (but you then get the
repeating keyboard events :/).

Please advice!On Wed, 10 Apr 2013 14:44:53 +0400 Driedfruit <@Driedfruit> wrote:

Hello list!

On X11, sometimes, when you move your mouse and release the keyboard
key at the same time, you get a SIGSERV crash. (see dumps and demo
program at the end)

I’ve “tracked” it down to the X11_KeyRepeat function in
SDL_x11events.c. The function looks for next X11 event in the queue
and compares it to the current one, working around keyboard
auto-repeat feature of X11.

The culprit is XPeekEvent, which either crashes itself, either
corrupts something, so next XNextEvent call crashes.

Now, as far as I can tell, SDL does everything correctly. So it might
be a bug in libX11 or my video driver.

However, some things are a bit weird. This never happens with
SDL1.2, altho I compared the code for X11_KeyRepeat and related and
it looked very very similar…

Additionally, something tells me this doesn’t happen for regular X11
programs, but I don’t have any proof for this yet, going to try it
next.

Also, if I remove the SDL_Delay() call, the bug seems to be gone, so I
might be doing something wrong in the first place. Are SDL_Delay()
calls not considered good practice in SDL2 ?

I’d be very grateful if you guys would test this. If you’re not seeing
the crash, you can change the “2” in the following line to “10” or a
larger value, makes it easier to trigger:

src/video/x11/SDL_x11events.c:113
((peekevent.xkey.time-event->xkey.time) < 2)) {

You’re aiming to “inject” a MotionNotify event inbetween the
KeyRelease and the auto-repeated KeyPress. For me, it crashes reliably
when this happens.

(I use libX11 1.4.1 and nvidia-driver 295.49)

test program:

#include <SDL.h>

int main(int argc, char* argv[])
{
SDL_Window* window;
SDL_Renderer *renderer;

    SDL_Init(SDL_INIT_VIDEO);
    window = SDL_CreateWindow("X11_KeyPreat problem",
                    SDL_WINDOWPOS_CENTERED,

SDL_WINDOWPOS_CENTERED, 512, 512,
SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, 0);
SDL_SetRenderDrawColor(renderer, 0xFF, 0, 0, 255);
SDL_RenderClear(renderer);

    int done = 0;

    while (!done) {
        SDL_Event event;
        SDL_zero(event);
		while (SDL_PollEvent(&event)) {
			if (event.type == SDL_QUIT) done = 1;
		}
		SDL_RenderPresent(renderer);
		//SDL_Delay(10);

}

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;

}

gdb backtrace:

#0 0xb7fe1424 in __kernel_vsyscall ()
#1 0xb7d85451 in raise () from /lib/libc.so.6
#2 0xb7d86b92 in abort () from /lib/libc.so.6
#3 0xb7dc09f5 in ?? () from /lib/libc.so.6
#4 0xb7dc6861 in ?? () from /lib/libc.so.6
#5 0xb7dc966d in ?? () from /lib/libc.so.6
#6 0xb7dcb27c in malloc () from /lib/libc.so.6
#7 0xb7c3944c in _XStoreEventCookie () from /usr/lib/libX11.so.6
#8 0xb7c284bc in XPeekEvent () from /usr/lib/libX11.so.6
#9 0xb7fa46a5 in XPeekEvent (a=0x804e788, b=0xbfffeccc)
at …/src/video/x11/SDL_x11sym.h:94
#10 0xb7fb519b in X11_KeyRepeat (_this=0x804dd58)
at …/src/video/x11/SDL_x11events.c:110
#11 X11_DispatchEvent
(_this=0x804dd58)at …/src/video/x11/SDL_x11events.c:444
#12 X11_PumpEvents (_this=0x804dd58)
at …/src/video/x11/SDL_x11events.c:914
#13 0xb7f33c84 in SDL_PumpEvents () at …/src/events/SDL_events.c:309
#14 0xb7f341ba in SDL_WaitEventTimeout (event=0xbfffef90,timeout=0)
at …/src/events/SDL_events.c:342
#15 0xb7f34295 in SDL_PollEvent(event=0xbfffef90)
at …/src/events/SDL_events.c:324 #16 0x080488e8 in main (argc=1,
argv=0xbffff094) at event.c:22

Relevant valgrind output:

==32494== Invalid write of size 1
==32494== at 0x4027164: memcpy
==32494== by 0x486C3F4: ??? (in /usr/lib/libXi.so.6.1.0)
==32494== by
0x472E7C7:_XCopyEventCookie(in /usr/lib/libX11.so.6.3.0) ==32494==
by 0x471E481: XPeekEvent (in /usr/lib/libX11.so.6.3.0) ==32494== by
0x40D06A4: XPeekEvent (SDL_x11sym.h:94) ==32494== by 0x40E119A:
X11_PumpEvents (SDL_x11events.c:110) ==32494== by 0x405FC83:
SDL_PumpEvents (SDL_events.c:309) ==32494== by 0x40601B9:
SDL_WaitEventTimeout (SDL_events.c:342) ==32494== by 0x4060294:
SDL_PollEvent (SDL_events.c:324) ==32494== by 0x80488E7:
main(event.c:22) ==32494== Address 0x707f29b is 7 bytes after a block
of size 60 alloc’d ==32494== at 0x402582E: malloc
==32494== by 0x486C341: ??? (in /usr/lib/libXi.so.6.1.0)
==32494== by
0x472E7C7:_XCopyEventCookie(in /usr/lib/libX11.so.6.3.0) ==32494==
by 0x471E481: XPeekEvent (in /usr/lib/libX11.so.6.3.0) ==32494== by
0x40D06A4: XPeekEvent (SDL_x11sym.h:94) ==32494== by 0x40E119A:
X11_PumpEvents (SDL_x11events.c:110) ==32494== by 0x405FC83:
SDL_PumpEvents (SDL_events.c:309) ==32494== by 0x40601B9:
SDL_WaitEventTimeout (SDL_events.c:342) ==32494== by 0x4060294:
SDL_PollEvent (SDL_events.c:324) ==32494== by 0x80488E7:
main(event.c:22)


driedfruit

I see the exact same error on Suse 12.1 in a game I just ported to SDL 2 2.0.0. In the game, it’s really easy to trigger: as soon as you start hitting keyboard keys and moving the mouse at the same time, it crashes. The gdb backtrace is practically identical to the one you posted.

My programming instincts say that this is a bug in SDL 2, not libX11, though I have no Xlib programming experience, so my instincts aren’t necessarily good. Here’s what I’ve tried:

  • adding code in X11_KeyRepeat to initialize peekevent.
  • adding code in X11_KeyRepeat to throw out the KeyPress event, which is something SDL 1.2.15 does.
  • moving the call of X11_KeyRepeat in X11_DispatchEvent up to just after the call to XNextEvent, again copying SDL 1.2.15.

These changes had no effect on the error. I’m out of ideas for simple things to try for now.

I guess I will have to use SDL 1 until this apparent bug in SDL 2 is fixed.

I’ve done some more investigating, and I don’t think this error has anything to do with KeyRelease events; I think it’s all about cookies and generic events (see XGenericEventCookie, XGetEventData, and XFreeEventData). In SDL 1.2.15, generic events and cookies were not used. In SDL 2 2.0.0, these things are used for XInput2 events, including raw mouse motion events and touch events.

If I comment out the line:

XISetMask(mask, XI_RawMotion);

in SDL_x11xinput2.c, the error goes away, but I stop getting mouse motion events. This suggests that the error is the result of improper handling of XI_RawMotion events (a type of generic event), not KeyRelease events. I think maybe the error is triggered by calling XPeekEvent when the event peeked at is a generic event. This can happen in X11_KeyRepeat (as a result of a KeyRelease event) or in other places such as X11_IsWheelEvent.

I still don’t know where the bug is. I’ve tried tweaking the handling of generic events in SDL_x11events.c in lots of different ways, and nothing seems to help. I don’t even know if this bug is in SDL 2 or Xlib.

Hi!

Is it by any chance this bug?

http://bugzilla.libsdl.org/show_bug.cgi?id=1812

Are you using libXi <= 1.4.1 ?On Sat, 13 Jul 2013 05:53:32 -0700 “sts1hvnx” wrote:

I’ve done some more investigating, and I don’t think this error has
anything to do with KeyRelease events; I think it’s all about cookies
and generic events (see XGenericEventCookie, XGetEventData, and
XFreeEventData). In SDL 1.2.15, generic events and cookies were not
used. In SDL 2 2.0.0, these things are used for XInput2 events,
including raw mouse motion events and touch events.

If I comment out the line:

XISetMask(mask, XI_RawMotion);

in SDL_x11xinput2.c, the error goes away, but I stop getting mouse
motion events. This suggests that the error is the result of
improper handling of XI_RawMotion events (a type of generic event),
not KeyRelease events. I think maybe the error is triggered by
calling XPeekEvent when the event peeked at is a generic event. This
can happen in X11_KeyRepeat (as a result of a KeyRelease event) or in
other places such as X11_IsWheelEvent.

I still don’t know where the bug is. I’ve tried tweaking the
handling of generic events in SDL_x11events.c in lots of different
ways, and nothing seems to help. I don’t even know if this bug is in
SDL 2 or Xlib.


driedfruit

Yes, it’s that bug. I managed to track it down to copyRawEvent() in XExtInt.c in libXi just a few minutes ago. It looks like this bug in libXi is fixed in libXi >= 1.4.3.

So apparently SDL 2 2.0.0 requires libXi’s version to be at least 1.4.3. This version of libXi was released on 2011-06-07. Perhaps someone should modify SDL 2 so that it works with older versions of libXi.

Yes, it’s that bug. I managed to track it down to copyRawEvent() in
XExtInt.c in libXi just a few minutes ago. It looks like this bug in
libXi is fixed in libXi >= 1.4.3.

Annoying part is, there are lots of debian machines out there with
libXi 1.4.1 :confused:

So apparently SDL 2 2.0.0 requires libXi’s version to be at least
1.4.3. This version of libXi was released on 2011-06-07. Perhaps
someone should modify SDL 2 so that it works with older versions of
libXi.

I’d suggest a ./configure check to be added, since, indeed, SDL2 will
not work correctly with earlier versions of libXi.

Fixing SDL2 to work-around this bug would be close to impossible, as
it’s a memory corruption issue, and I guess reverting all the XInput
changes (use of cookies) to SDL1.2 state isn’t an option either.On Sat, 13 Jul 2013 11:29:15 -0700 “sts1hvnx” wrote:


driedfruit

I see two approaches to modifying SDL 2 to deal with this problem: dodging the bug, and falling back to old ways.

  1. Dodging the bug

In order to dodge the bug, you would avoid calling the function with the bug, copyRawEvent in XExtInt.c in libXi. This is called from just one place, XInputCopyCookie in the same file; this call only happens if the event type is one that uses the XIRawEvent data structure. XInputCopyCookie, in turn, is called from just one place, _XCopyEventCookie in XlibInt.c in libX11; this call only happens if the event being copied is a libXi generic event. _XCopyEventCookie is called from three places in libX11: XPeekIfEvent, XPeekEvent, and _XPutBackEvent. The first two are libX11 external interface functions and are not called internally. The third is called internally in two places: XPutBackEvent and _XimLocalFilter. The call from _XimLocalFilter never puts back a generic event, so it’s safe. XPutBackEvent, in addition to being a libX11 external interface function, is called from seven places internally: _XimXGetReadData, _XimTransInternalConnection, _XimForwardEventRecv, _XimCommitRecv, _XimLocalFilter, _XimProcExtForwardKeyEvent, and _XimThaiFilter. For every one of these Xim functions, as far as I can tell, the event passed to XPutBackEvent is a non-generic event generated internally.

So the buggy function, copyRawEvent in libXi, is only called if you call one of the three libX11 functions XPeekIfEvent, XPeekEvent, or XPutBackEvent (and only then if the event being copied is a libXi generic event wrapping an XIRawEvent). XPeekIfEvent and XPutBackEvent are not called from SDL2. XPeekEvent is called from just two places in SDL2: in X11_KeyRepeat and X11_IsWheelEvent, both in src/video/x11/SDL_x11events.c.

So to dodge the bug, SDL2’s X11_KeyRepeat and X11_IsWheelEvent functions would have to be modified so that they don’t call XPeekEvent, without using XPutBackEvent or XPeekIfEvent instead. In both SDL functions, there is an obvious alternative to XPeekEvent: XCheckIfEvent.

In fact, both X11_KeyRepeat and X11_IsWheelEvent appear (to me) to have subtle bugs because they currently use XPeekEvent instead of XCheckIfEvent. XPeekEvent only checks the next event in the queue for the target event, while XCheckIfEvent can check the entire queue for the target event.

So despite the complexity of the above analysis, dodging the bug appears to be really easy, and would potentially fix some subtle bugs in X11_KeyRepeat and X11_IsWheelEvent. All you have to do is rewrite these two functions so that they use XCheckIfEvent instead of XPeekEvent.

(Question: is there some good reason why these two SDL functions use XPeekEvent instead of XCheckIfEvent?)

  1. Falling back to old ways

As far as I can tell, SDL2 uses just 4 XInput2 generic event types: XI_RawMotion, XI_TouchBegin, XI_TouchEnd, and XI_TouchUpdate. The three touch events use the libXi XIDeviceEvent data structure, and so are immune to the bug in libXi. So in SDL2, only XI_RawMotion events use the XIRawEvent data structure whose copy function, copyRawEvent in libXi, is buggy. In SDL2, XI_RawMotion is only used to capture mouse motion events when the mouse is in “relative mode” (set with SDL_SetRelativeMouseMode). Non-relative-mode mouse motion events are handled with the ordinary MotionNotify X event.

In SDL 1.2.15, relative mode mouse motion events are handled with MotionNotify, just as non-relative-mode mouse motion events are. A special function, X11_WarpedMotion, is needed (for reasons that are not clear to me) to handle the relative-mode mouse motion event.

So to deal with the libXi bug this way, if the libXi version is >= 1.4.3, we would use the new XI_RawMotion code for relative-mode mouse motion events, and if the libXi version is < 1.4.3, we would use the old MotionNotify with X11_WarpedMotion code.

Note that XInput2 support was added to libXi around 2009, approximately version 1.3. For versions of libXi older than this, as well as when the X server does not support XInput2, SDL2 should probably do relative-mode mouse motion events the old way (using MotionNotify) anyway.

(I am totally unfamiliar with programming with “./configure”, so it would be very painful for me to try to write a patch for SDL2 using this “falling back to old ways” method.)

  1. Conclusion

In my opinion, both of the above methods for dealing with this libXi bug in SDL2 are good ones. If I were to pick which one to do, I would pick BOTH: the first one because it might fix some subtle bugs with autorepeat and wheel events in addition to dodging the libXi bug, and the second because it’s necessary in order for relative-mode mouse motion events to work correctly in the absence of XInput2. If I had to write the code for this, I would be comfortable writing the first one but not the second, because of my lack of experience with configure (unless a configure-less way of doing the second were chosen).

I hope the SDL powers-that-be will add some workaround to SDL2 for this libXi bug, whether it is one of my suggestions above, both, or something completely different.

The libXi bug workaround labeled “Dodging the bug” in my previous post seemed so easy to me to implement that I went ahead and did it. The following code replaces the X11_KeyRepeat and X11_IsWheelEvent functions in SDL2’s src/video/x11/SDL_x11events.c. I’ve tested it on my Suse 12.1 machine, which has libXi 1.4.0, and it works.

Code:

struct KeyRepeatCheckData
{
XEvent *event;
SDL_bool found;
};

static Bool X11_KeyRepeatCheckIfEvent(Display *display, XEvent *chkev,
XPointer arg)
{
struct KeyRepeatCheckData *d = (struct KeyRepeatCheckData *) arg;
if (chkev->type == KeyPress &&
chkev->xkey.keycode == d->event->xkey.keycode &&
chkev->xkey.time - d->event->xkey.time < 2)
d->found = SDL_TRUE;
return False;
}

static SDL_bool X11_KeyRepeat(Display *display, XEvent *event)
{
XEvent dummyev;
struct KeyRepeatCheckData d;
d.event = event;
d.found = SDL_FALSE;
XCheckIfEvent(display, &dummyev, X11_KeyRepeatCheckIfEvent, (XPointer) &d);
return d.found;
}

static Bool X11_IsWheelCheckIfEvent(Display *display, XEvent *chkev,
XPointer arg)
{
XEvent *event = (XEvent *) arg;
if (chkev->type == ButtonRelease &&
chkev->xbutton.button == event->xbutton.button &&
chkev->xbutton.time == event->xbutton.time)
return True;
return False;
}

static SDL_bool X11_IsWheelEvent(Display * display,XEvent * event,int * ticks)
{
XEvent relevent;
if (XPending(display)) {
/* according to the xlib docs, no specific mouse wheel events exist.
however, mouse wheel events trigger a button press and
a button release immediately. thus, checking if the same
button was released at the same time as it was pressed,
should be an adequate hack to derive a mouse wheel event. */
if (XCheckIfEvent(display, &relevent, X11_IsWheelCheckIfEvent,
(XPointer) event)) {

        /* by default, X11 only knows 5 buttons. on most 3 button
           + wheel mouse, Button4 maps to wheel up, Button5 maps to
           wheel down. */
        if (event->xbutton.button == Button4) {
            *ticks = 1;
        }
        else if (event->xbutton.button == Button5) {
            *ticks = -1;
        }
        return SDL_TRUE;
    }
}
return SDL_FALSE;

}

Note that, in addition to working around this libXi bug, the above new code is probably faster than the old code because it never triggers copying an XGenericEventCookie, which involves allocating memory.

Also note that, even if you put the above code in SDL2 to patch this problem, I still think code should be added to fall back to the old way of doing things (with MotionNotify instead of XI_RawMotion) when XInput2 is not available in libXi and the X server.

Can you attach this as a patch to that bug, if applicable?
http://bugzilla.libsdl.org/show_bug.cgi?id=1812

Jonny DOn Mon, Jul 15, 2013 at 11:54 AM, sts1hvnx wrote:

**
The libXi bug workaround labeled “Dodging the bug” in my previous post
seemed so easy to me to implement that I went ahead and did it. The
following code replaces the X11_KeyRepeat and X11_IsWheelEvent functions in
SDL2’s src/video/x11/SDL_x11events.c. I’ve tested it on my Suse 12.1
machine, which has libXi 1.4.0, and it works.

Code:

struct KeyRepeatCheckData
{
XEvent *event;
SDL_bool found;
};

static Bool X11_KeyRepeatCheckIfEvent(Display *display, XEvent *chkev,
XPointer arg)
{
struct KeyRepeatCheckData *d = (struct KeyRepeatCheckData *) arg;
if (chkev->type == KeyPress &&
chkev->xkey.keycode == d->event->xkey.keycode &&
chkev->xkey.time - d->event->xkey.time < 2)
d->found = SDL_TRUE;
return False;
}

static SDL_bool X11_KeyRepeat(Display *display, XEvent *event)
{
XEvent dummyev;
struct KeyRepeatCheckData d;
d.event = event;
d.found = SDL_FALSE;
XCheckIfEvent(display, &dummyev, X11_KeyRepeatCheckIfEvent, (XPointer)
&d);
return d.found;
}

static Bool X11_IsWheelCheckIfEvent(Display *display, XEvent *chkev,
XPointer arg)
{
XEvent *event = (XEvent *) arg;
if (chkev->type == ButtonRelease &&
chkev->xbutton.button == event->xbutton.button &&
chkev->xbutton.time == event->xbutton.time)
return True;
return False;
}

static SDL_bool X11_IsWheelEvent(Display * display,XEvent * event,int *
ticks)
{
XEvent relevent;
if (XPending(display)) {
/* according to the xlib docs, no specific mouse wheel events
exist.
however, mouse wheel events trigger a button press and
a button release immediately. thus, checking if the same
button was released at the same time as it was pressed,
should be an adequate hack to derive a mouse wheel event. */
if (XCheckIfEvent(display, &relevent, X11_IsWheelCheckIfEvent,
(XPointer) event)) {

        /* by default, X11 only knows 5 buttons. on most 3 button
           + wheel mouse, Button4 maps to wheel up, Button5 maps to
           wheel down. */
        if (event->xbutton.button == Button4) {
            *ticks = 1;
        }
        else if (event->xbutton.button == Button5) {
            *ticks = -1;
        }
        return SDL_TRUE;
    }
}
return SDL_FALSE;

}

Note that, in addition to working around this libXi bug, the above new
code is probably faster than the old code because it never triggers copying
an XGenericEventCookie, which involves allocating memory.

Also note that, even if you put the above code in SDL2 to patch this
problem, I still think code should be added to fall back to the old way of
doing things (with MotionNotify instead of XI_RawMotion) when XInput2 is
not available in libXi and the X server.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Jonny D wrote:

Can you attach this as a patch to that bug, if applicable?http://bugzilla.libsdl.org/show_bug.cgi?id=1812 (http://bugzilla.libsdl.org/show_bug.cgi?id=1812)

Done.

(Note that I created a bugzilla account for myself with a temporary email address that will stop working as soon as I get any junk mail on it. So if you wish to contact me, do it through this forum thread rather than through bugzilla.)

Some amazing detective work there. I was struggling today with a crash
happening in XNextEvent in X11_DispatchEvent in SDL_x11events.c. Googling
eventually brought me to this email thread. It turns out I’m using
libXi-1.3.2, and your patch makes my crash go away. Thanks. Consider this
another vote for using your patch.–
Terry Welsh
www.reallyslick.com

Message: 1
Date: Mon, 15 Jul 2013 12:38:17 -0700
From: “sts1hvnx”
To: sdl at lists.libsdl.org
Subject: Re: [SDL] X11_KeyRepeat crash
Message-ID: <1373917097.m2f.38072 at forums.libsdl.org>
Content-Type: text/plain; charset=“iso-8859-1”

Jonny D wrote:

Can you attach this as a patch to that bug, if applicable?
http://bugzilla.libsdl.org/show_bug.cgi?id=1812 (
http://bugzilla.libsdl.org/show_bug.cgi?id=1812)

Done.

(Note that I created a bugzilla account for myself with a temporary email
address that will stop working as soon as I get any junk mail on it. So if
you wish to contact me, do it through this forum thread rather than through
bugzilla.)

I was wondering if this whole thing was related to the bad free I sometimes receive on older linux systems with XNextEvent.

It plagued Torchlight’s linux port that I did last year… Though mostly on older system (Debian 6, CentOS 6, Ubuntu 10)… But for TL it always seemed to be related to mouse input…

Torchlight thread http://forums.runicgames.com/viewtopic.php?f=24&t=33482#p310430

Edward Rudd
OutOfOrder.cc
Skype: outoforder_cc
317-674-3296On Jul 18, 2013, at 5:57 PM, Terry Welsh wrote:

Some amazing detective work there. I was struggling today with a crash happening in XNextEvent in X11_DispatchEvent in SDL_x11events.c. Googling eventually brought me to this email thread. It turns out I’m using libXi-1.3.2, and your patch makes my crash go away. Thanks. Consider this another vote for using your patch.

Terry Welsh
www.reallyslick.com

Message: 1
Date: Mon, 15 Jul 2013 12:38:17 -0700
From: “sts1hvnx”
To: sdl at lists.libsdl.org
Subject: Re: [SDL] X11_KeyRepeat crash
Message-ID: <1373917097.m2f.38072 at forums.libsdl.org>
Content-Type: text/plain; charset=“iso-8859-1”

Jonny D wrote:

Can you attach this as a patch to that bug, if applicable?http://bugzilla.libsdl.org/show_bug.cgi?id=1812 (http://bugzilla.libsdl.org/show_bug.cgi?id=1812)

Done.

(Note that I created a bugzilla account for myself with a temporary email address that will stop working as soon as I get any junk mail on it. So if you wish to contact me, do it through this forum thread rather than through bugzilla.)


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I was wondering if this whole thing was related to the bad free I
sometimes receive on older linux systems with XNextEvent.

I was wondering that, too. We’re probably applying this patch shortly.

–ryan.

urkle wrote:

I was wondering if this whole thing was related to the bad free I sometimes receive on older linux systems with XNextEvent.

It plagued Torchlight’s linux port that I did last year… Though mostly on older system (Debian 6, CentOS 6, Ubuntu 10)… But for TL it always seemed to be related to mouse input…

Torchlight thread http://forums.runicgames.com/viewtopic.php?f=24&t=33482#p310430 (http://forums.runicgames.com/viewtopic.php?f=24&t=33482#p310430)

Looking at the crash report in that thread, it certainly looks like the same error to me. And you seemed to reach the conclusion that it was caused by a bug in libXi, too.>From my analysis, I think there are two ways to trigger the error: moving the mouse while releasing a key; and moving the mouse while turning the mouse wheel. Was one of those the trigger in Torchlight?

The call stacks in that Torchlight thread look just like the problem I was
having, starting with SDL_PollEvent and the last X call being XFree. It
sounds like everyone was triggering the problem in a different way, though.
I was getting crashes on keyboard input when I started a new game or
toggled fullscreen mode.–
Terry Welsh
www.reallyslick.com

I was wondering if this whole thing was related to the bad free I
sometimes receive on older linux systems with XNextEvent.

It plagued Torchlight’s linux port that I did last year… Though mostly
on older system (Debian 6, CentOS 6, Ubuntu 10)… But for TL it always
seemed to be related to mouse input…

Torchlight thread
http://forums.runicgames.com/viewtopic.php?f=24&t=33482#p310430

Edward Rudd

The patch is now in revision control. Next time you update, everyone let
me know if the problem went away.

Thanks!

–ryan.On 7/19/13 11:31 AM, Terry Welsh wrote:

The call stacks in that Torchlight thread look just like the problem I
was having, starting with SDL_PollEvent and the last X call being XFree.
It sounds like everyone was triggering the problem in a different way,
though. I was getting crashes on keyboard input when I started a new
game or toggled fullscreen mode.

No more crashes since I updated. Thank you.–
Terry Welsh
www.reallyslick.com

The patch is now in revision control. Next time you update, everyone let

me know if the problem went away.

Thanks!

–ryan.