Subject: Re: proposed fix for XF4 crashing
To: IWAMOTO Toshihiro <iwamoto@sat.t.u-tokyo.ac.jp>
From: Matthieu Herrb <matthieu.herrb@laas.fr>
List: tech-x11
Date: 01/09/2002 01:22:07
You wrote (in your message from Tuesday 8)
 > 
 > My guess is that the crashes are due to race between pointer motion
 > event queueing (which happens from signal handler) and removal of
 > events from the queue.
 > 
Totally removing the SIGIO handler is not a good idea. 
The code handling the events from SIGIO is supposed to be
safe. However, there's a bug in XFree86 4.1.0 that causes malloc/free
to be called from the sig handler, which is bad. 

The following patch, by Keith Packard, form XFree86 CVS repository
fixes this bug. Other users that have reported the same kind of
crashes say the server doesn't crash anymore with this patch. 

===================================================================
RCS file: /home/anoncvs/cvs-public/xc/programs/Xserver/hw/xfree86/input/mouse/mouse.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -p -r1.43 -r1.44
--- xc/programs/Xserver/hw/xfree86/input/mouse/mouse.c	2001/05/18 20:22:30	1.43
+++ xc/programs/Xserver/hw/xfree86/input/mouse/mouse.c	2001/07/06 08:02:37	1.44
@@ -1,4 +1,4 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/input/mouse/mouse.c,v 1.42 2001/05/15 18:22:22 paulo Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/input/mouse/mouse.c,v 1.43 2001/05/18 20:22:30 tsi Exp $ */
 /*
  *
  * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
@@ -386,6 +386,14 @@ InitProtocols(void)
     return TRUE;
 }
 
+static void MouseBlockHandler(pointer data,
+			      struct timeval **waitTime,
+			      pointer LastSelectMask);
+
+static void MouseWakeupHandler(pointer data,
+			       int i,
+			       pointer LastSelectMask);
+
 /* Process options common to all mouse types. */
 static void
 MouseCommonOptions(InputInfoPtr pInfo)
@@ -411,6 +419,8 @@ MouseCommonOptions(InputInfoPtr pInfo)
     if (pMse->emulate3Buttons) {
 	xf86Msg(X_CONFIG, "%s: Emulate3Buttons, Emulate3Timeout: %d\n",
 		pInfo->name, pMse->emulate3Timeout);
+	RegisterBlockAndWakeupHandlers (MouseBlockHandler, MouseWakeupHandler,
+					(pointer) pInfo);
     }
 
     pMse->chordMiddle = xf86SetBoolOption(pInfo->options, "ChordMiddle", FALSE);
@@ -1822,18 +1832,17 @@ static char hitachMap[16] = {  0,  2,  1
 #define reverseBits(map, b)	(((b) & ~0x0f) | map[(b) & 0x0f])
 
 static CARD32
-buttonTimer(OsTimerPtr timer, CARD32 now, pointer arg)
+buttonTimer(InputInfoPtr pInfo)
 {
-    InputInfoPtr pInfo;
     MouseDevPtr pMse;
     int	sigstate;
     int id;
 
-    pInfo = arg;
     pMse = pInfo->private;
 
     sigstate = xf86BlockSIGIO ();
 
+    pMse->emulate3Pending = FALSE;
     if ((id = stateTab[pMse->emulateState][4][0]) != 0) {
         xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
         pMse->emulateState = stateTab[pMse->emulateState][4][2];
@@ -1845,10 +1854,42 @@ buttonTimer(OsTimerPtr timer, CARD32 now
     return 0;
 }
 
+static void MouseBlockHandler(pointer data,
+			      struct timeval **waitTime,
+			      pointer LastSelectMask)
+{
+    InputInfoPtr    pInfo = (InputInfoPtr) data;
+    MouseDevPtr	    pMse = (MouseDevPtr) pInfo->private;
+    int		    ms;
+
+    if (pMse->emulate3Pending)
+    {
+	ms = pMse->emulate3Expires - GetTimeInMillis ();
+	if (ms <= 0)
+	    ms = 0;
+	AdjustWaitForDelay (waitTime, ms);
+    }
+}
+
+static void MouseWakeupHandler(pointer data,
+			       int i,
+			       pointer LastSelectMask)
+{
+    InputInfoPtr    pInfo = (InputInfoPtr) data;
+    MouseDevPtr	    pMse = (MouseDevPtr) pInfo->private;
+    int		    ms;
+    
+    if (pMse->emulate3Pending)
+    {
+	ms = pMse->emulate3Expires - GetTimeInMillis ();
+	if (ms <= 0)
+	    buttonTimer (pInfo);
+    }
+}
+
 static void
 MouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy)
 {
-    static OsTimerPtr timer = NULL;
     MouseDevPtr pMse;
     int truebuttons, emulateButtons;
     int id, change;
@@ -1890,13 +1931,10 @@ MouseDoPostEvent(InputInfoPtr pInfo, int
                 stateTab[pMse->emulateState][emulateButtons][2];
 
             if (stateTab[pMse->emulateState][4][0] != 0) {
-                timer = TimerSet(timer, 0, pMse->emulate3Timeout, buttonTimer,
-			     pInfo);
+		pMse->emulate3Expires = GetTimeInMillis () + pMse->emulate3Timeout;
+		pMse->emulate3Pending = TRUE;
             } else {
-                if (timer) {
-                    TimerFree(timer);
-                    timer = NULL;
-                }
+		pMse->emulate3Pending = FALSE;
             }
         }
 
===================================================================
RCS file: /home/anoncvs/cvs-public/xc/programs/Xserver/hw/xfree86/os-support/xf86OSmouse.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -p -r1.14 -r1.15
--- xc/programs/Xserver/hw/xfree86/os-support/xf86OSmouse.h	2001/03/07 16:21:04	1.14
+++ xc/programs/Xserver/hw/xfree86/os-support/xf86OSmouse.h	2001/07/06 08:02:39	1.15
@@ -1,4 +1,4 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86OSmouse.h,v 1.13 2001/03/04 01:43:28 tsi Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86OSmouse.h,v 1.14 2001/03/07 16:21:04 paulo Exp $ */
 
 /*
  * Copyright (c) 1997-1999 by The XFree86 Project, Inc.
@@ -140,6 +140,8 @@ typedef struct _MouseDevRec {
     InputInfoPtr	pInfo;
     int			origProtocolID;
     const char *	origProtocol;
+    Bool		emulate3Pending;/* timer waiting */
+    CARD32		emulate3Expires;/* time to fire emulation code */
 } MouseDevRec, *MouseDevPtr;
 
 /* Z axis mapping */

-- 
					Matthieu