Re: [AD] timer_mutex again

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


Eric Botcazou wrote:

So thread 4 is holding the timer_mutex in _handle_timer_tick() and
wanting to get the _xwin.mutex.  Meanwhile thread 1 has the _xwin.mutex
(due to an acquire_screen in dialog_message) and wants the timer_mutex.

Thanks. I think dialog_message is wrong, it should not acquire_screen. AFAICS object_message already has the necessary bits.

scare_mouse clearly cannot be invoked when the screen has been acquired.

Ah, cheers! Attached is a patch for dialog_message() instead, with a verbose explanation.

The idea was to make sure that all callbacks have completed before
remove_int returns.  Does your proposed change still guarantee that?
No :-(  Actually, the same problem is marked FIXME in the new_api_branch
so I should have remembered it.

I should have documented it in timer.c.
Patch attached; what do you think?

Peter
Index: src/gui.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/gui.c,v
retrieving revision 1.74
diff -u -r1.74 gui.c
--- src/gui.c	7 Apr 2005 21:59:36 -0000	1.74
+++ src/gui.c	18 Apr 2005 12:13:23 -0000
@@ -364,8 +364,21 @@
    DIALOG *menu_dialog = NULL;
    ASSERT(dialog);
 
-   if (msg == MSG_DRAW)
-      acquire_screen();
+   /* Note: don't acquire the screen in here.  A deadlock develops in a
+    * situation like this:
+    *
+    * 1. this thread: acquires the screen;
+    * 2. timer thread: wakes up, locks the timer_mutex, and calls a
+    *    callback to redraw the software mouse cursor, which tries to
+    *    acquire the screen;
+    * 3. this thread: object_message(MSG_DRAW) calls scare_mouse()
+    *    which calls remove_int().
+    *
+    * So this thread has the screen acquired and wants the timer_mutex,
+    * whereas the timer thread holds the timer_mutex, but wants to acquire
+    * the screen.  The problem is calling scare_mouse() with the screen
+    * acquired.
+    */
 
    force = ((msg == MSG_START) || (msg == MSG_END) || (msg >= MSG_USER));
 
@@ -409,9 +422,6 @@
 	 break;
    }
 
-   if (msg == MSG_DRAW)
-      release_screen();
-
    return res;
 }
 
Index: src/timer.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/timer.c,v
retrieving revision 1.20
diff -u -r1.20 timer.c
--- src/timer.c	14 Mar 2005 11:41:59 -0000	1.20
+++ src/timer.c	18 Apr 2005 12:27:01 -0000
@@ -50,6 +50,16 @@
 
 #ifdef ALLEGRO_MULTITHREADED
 static void *timer_mutex = NULL;          /* global timer mutex */
+   /* Why we need timer_mutex:
+    *
+    * 1. So _timer_queue[] is not changed in the middle of
+    * _handle_timer_tick's loop, possibly causing a null pointer
+    * dereference or corruption;
+    *
+    * 2. So that after "remove_int(my_callback);" returns, my_callback
+    * is guaranteed not to be in the _timer_queue and will not be
+    * called from the timer thread.
+    */
 #else
 static int timer_semaphore = FALSE;       /* reentrant interrupt? */
 #endif


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/