Blob Blame History Raw
From 7089841a7e026799328e97292c2f81aa4aa01f57 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Fri, 27 Apr 2012 10:52:39 +1000
Subject: [PATCH] os: make timers signal-safe

If TimerSet() is called from a signal handler (synaptics tap handling code)
may result in list corruption if we're currently inside TimerSet().

See backtrace in
https://bugzilla.redhat.com/show_bug.cgi?id=814869

Block signals for all list manipulations in the timers.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Chase Douglas <chase.douglas@canonical.com>
(cherry picked from commit 08962951de969b9d8c870af8b6e47303dc0decfd)

Conflicts:

	os/WaitFor.c
---
 os/WaitFor.c |   18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/os/WaitFor.c b/os/WaitFor.c
index 867cb04..236406e 100644
--- a/os/WaitFor.c
+++ b/os/WaitFor.c
@@ -405,6 +405,7 @@ CheckAllTimers(void)
     OsTimerPtr timer;
     CARD32 now;
 
+    OsBlockSignals();
 start:
     now = GetTimeInMillis();
 
@@ -414,6 +415,7 @@ start:
             goto start;
         }
     }
+    OsReleaseSignals();
 }
 
 static void
@@ -421,11 +423,13 @@ DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev)
 {
     CARD32 newTime;
 
+    OsBlockSignals();
     *prev = timer->next;
     timer->next = NULL;
     newTime = (*timer->callback)(timer, now, timer->arg);
     if (newTime)
 	TimerSet(timer, 0, newTime, timer->callback, timer->arg);
+    OsReleaseSignals();
 }
 
 OsTimerPtr
@@ -443,6 +447,7 @@ TimerSet(OsTimerPtr timer, int flags, CARD32 millis,
     }
     else
     {
+        OsBlockSignals();
 	for (prev = &timers; *prev; prev = &(*prev)->next)
 	{
 	    if (*prev == timer)
@@ -453,6 +458,7 @@ TimerSet(OsTimerPtr timer, int flags, CARD32 millis,
 		break;
 	    }
 	}
+        OsReleaseSignals();
     }
     if (!millis)
 	return timer;
@@ -473,29 +479,35 @@ TimerSet(OsTimerPtr timer, int flags, CARD32 millis,
 	if (!millis)
 	    return timer;
     }
+    OsBlockSignals();
     for (prev = &timers;
 	 *prev && (int) ((*prev)->expires - millis) <= 0;
 	 prev = &(*prev)->next)
         ;
     timer->next = *prev;
     *prev = timer;
+    OsReleaseSignals();
     return timer;
 }
 
 Bool
 TimerForce(OsTimerPtr timer)
 {
+    int rc = FALSE;
     OsTimerPtr *prev;
 
+    OsBlockSignals();
     for (prev = &timers; *prev; prev = &(*prev)->next)
     {
 	if (*prev == timer)
 	{
 	    DoTimer(timer, GetTimeInMillis(), prev);
-	    return TRUE;
+	    rc = TRUE;
+	    break;
 	}
     }
-    return FALSE;
+    OsReleaseSignals();
+    return rc;
 }
 
 
@@ -506,6 +518,7 @@ TimerCancel(OsTimerPtr timer)
 
     if (!timer)
 	return;
+    OsBlockSignals();
     for (prev = &timers; *prev; prev = &(*prev)->next)
     {
 	if (*prev == timer)
@@ -514,6 +527,7 @@ TimerCancel(OsTimerPtr timer)
 	    break;
 	}
     }
+    OsReleaseSignals();
 }
 
 void
-- 
1.7.10.1