diff options
author | Steven McDonald <steven@steven-mcdonald.id.au> | 2014-05-18 13:42:08 +0200 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2014-06-27 09:47:59 +1000 |
commit | 2abbf56493bb8636ae1ef6de2cbb412ac79c717f (patch) | |
tree | cf1ddab4311924c5f4de4e226ee494810c227e9c | |
parent | 2ceb44827f86d9f5f995448c3cf603ee9459fef3 (diff) |
Xi: block SIGIOs while copying device classes around
I've been seeing sporadic (anywhere from once every few days to 3-4
times a day) crashes and freezes in X. The problematic behaviour isn't
always the same, but I chose a particular incident to debug, and found
that X was segfaulting in updateMotionHistory, on line 575 of
dix/getevents.c.
After some further investigation, I found that the bug was being
triggered when a SIGIO was received in DeepCopyPointerClasses, between
the AllocValuatorClass call (line 540) and updating the to->valuator
pointer (line 545). AllocValuatorClass calls realloc() on to->valuator,
so between these lines, it's not guaranteed to point to allocated
memory.
It seems the SIGIO handler is calling updateMotionHistory, which is
reading the memory pointed to by to->valuator and getting a wrong value
for last_motion, which updates buff to point to wildly the wrong place
and thus generates a segfault when a memcpy() is done into buff.
I am attaching a patch which I've been running on that machine for the
past three days, and haven't yet observed any more crashing or freezing
behaviour. The patch simply calls OsBlockSIGIO while
DeepCopyDeviceClasses is in progress, as the state of the X server's
device data structures is not guaranteed to be in a consistent state
during that time.
Debian bug#744303 <https://bugs.debian.org/744303>
Signed-off-by: Julien Cristau <jcristau@debian.org>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit d7a2df0a7499864cb005b098b79c1bdf884f6600)
-rw-r--r-- | Xi/exevents.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c index ad0265093..01bdea6df 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -661,6 +661,8 @@ void DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce) { + OsBlockSIGIO(); + /* generic feedback classes, not tied to pointer and/or keyboard */ DeepCopyFeedbackClasses(from, to); @@ -668,6 +670,8 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeepCopyKeyboardClasses(from, to); if ((dce->flags & DEVCHANGE_POINTER_EVENT)) DeepCopyPointerClasses(from, to); + + OsReleaseSIGIO(); } /** |