Comment 4 for bug 563100

Revision history for this message
In , Tim Yamin (plasmaroo) wrote :

Created an attachment (id=32354)
Patch for issue

Here's a description of what happens for me along with a patch that seems to fix my problem... My Xinerama setup is as follows:

    Screen 0 "Screen0"
    Screen 1 "Screen0 (2nd)" RightOf "Screen0"
    Screen 2 "Screen1" Below "Screen0"
    Screen 3 "Screen1 (2nd)" RightOf "Screen1"
    Screen 4 "Screen2" Below "Screen1"

Occasionally, X locks up during normal use and you see the mouse cursor "jumping around" the different screens. X is in a tight 100% CPU loop and you can't do anything other than kill it. The easiest way to reproduce the bug in about 30 seconds is to drag a window around between the screens like crazy...

The problem seems to be that there's some sort of nasty feedback loop that causes events to be fed into the event queue while the event queue is being processed:

(gdb) bt
#0 mieqEnqueue (pDev=0x85441c0, e=0x85787a8) at mieq.c:148
#1 0x0809dfc0 in miPointerWarpCursor (pDev=0x85441c0, pScreen=0x82d1a10, x=241, y=7) at mipointer.c:587
#2 0x08154faa in xf86WarpCursor (pDev=0x85441c0, pScreen=0x82d1a10, x=241, y=7) at xf86Cursor.c:473
#3 0x0809dcc3 in miPointerSetCursorPosition (pDev=0x85441c0, pScreen=0x82d1a10, x=241, y=7, generateEvent=1) at mipointer.c:239
#4 0x08109e21 in AnimCurSetCursorPosition (pDev=0x85441c0, pScreen=0x82d1a10, x=241, y=7, generateEvent=1) at animcur.c:266
#5 0x0807a4bc in XineramaSetCursorPosition (pDev=0x85441c0, x=<value optimized out>, y=<value optimized out>, generateEvent=1) at events.c:555
#6 0x0807a72d in CheckPhysLimits (pDev=0x85441c0, cursor=<value optimized out>, generateEvents=1, confineToScreen=0, pScreen=0x0) at events.c:772
#7 0x0807a8e5 in XineramaConfineCursorToWindow (pDev=0x85441c0, pWin=0x83359e8, generateEvents=1) at events.c:650
#8 0x0807ab9e in NewCurrentScreen (pDev=0x85441c0, newScreen=0x82d1a10, x=241, y=7) at events.c:3167
#9 0x080dea32 in mieqProcessDeviceEvent (dev=0x85441c0, event=0x85795b8, screen=0x82d1a10) at mieq.c:388
#10 0x080deb7f in mieqProcessInputEvents () at mieq.c:471
#11 0x080b7cff in ProcessInputEvents () at xf86Events.c:165
#12 0x0809756a in Dispatch () at dispatch.c:407
#13 0x08064d8d in main () at main.c:285

I compared the code in 1.6.5 (which doesn't have this issue) against 1.7.3.902 (which does). It looks like the problem is due to a regression between XineramaCheckPhysLimits and CheckPhysLimits being merged into one single function:

== OLD (dix/events.c; XineramaCheckPhysLimits used for Xinerama)

    if((new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
    {
    ...
    }

== OLD (dix/events.c; CheckPhysLimits used for non-Xinerama)

    if ((pScreen != pSprite->hotPhys.pScreen) ||
        (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
    {
    ...
    }

== NEW (dix/events.c; merged CheckPhysLimits used for Xinerama & non-Xinerama)

    if ((pScreen != pSprite->hotPhys.pScreen) ||
        (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
    {
    ...
    }

This patch reverts back to the original behaviour (pScreen check should only do something for the non-Xinerama code path) and this fixes the problem for me... if you're CC'd on this bug can you please test this patch?

Cheers,

Tim