emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master a9b8ebf34c: Fix races with child frame locks on Haiku


From: Po Lu
Subject: master a9b8ebf34c: Fix races with child frame locks on Haiku
Date: Thu, 14 Apr 2022 09:19:22 -0400 (EDT)

branch: master
commit a9b8ebf34c97098631bf0f4a0fb254ff2f2d898d
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Fix races with child frame locks on Haiku
    
    * src/haiku_support.cc
    (CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK): New macro.
    (FrameMoved, WorkspacesChanged): Lock child frame data with that
    macro instead.
---
 src/haiku_support.cc | 52 +++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 39 insertions(+), 13 deletions(-)

diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index 599ff305ae..f0db852e26 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -131,6 +131,29 @@ static void *grab_view = NULL;
 static BLocker grab_view_locker;
 static bool drag_and_drop_in_progress;
 
+/* Many places require us to lock the child frame data, and then lock
+   the locker of some random window.  Unfortunately, locking such a
+   window might be delayed due to an arriving message, which then
+   calls a callback inside that window that tries to lock the child
+   frame data but doesn't finish since the child frame lock is already
+   held, not letting the code that held the child frame lock proceed,
+   thereby causing a deadlock.
+
+   Rectifying that problem is simple: all code in a looper callback
+   must lock the child frame data with this macro instead.
+
+   IOW, If some other code is already running with the child frame
+   lock held, don't interfere: wait until it's finished before
+   continuing.  */
+#define CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK                \
+  if (child_frame_lock.LockWithTimeout (200) != B_OK)  \
+    {                                                  \
+      /* The Haiku equivalent of XPutBackEvent.  */    \
+      if (CurrentMessage ())                           \
+       PostMessage (CurrentMessage ());                \
+    }                                                  \
+  else
+
 /* This could be a private API, but it's used by (at least) the Qt
    port, so it's probably here to stay.  */
 extern status_t get_subpixel_antialiasing (bool *);
@@ -968,25 +991,28 @@ public:
 
     haiku_write (MOVE_EVENT, &rq);
 
-    if (!child_frame_lock.Lock ())
-      gui_abort ("Failed to lock child frame state lock");
-    for (struct child_frame *f = subset_windows;
-        f; f = f->next)
-      DoMove (f);
-    child_frame_lock.Unlock ();
+    CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK
+      {
+       for (struct child_frame *f = subset_windows;
+            f; f = f->next)
+         DoMove (f);
+       child_frame_lock.Unlock ();
 
-    BWindow::FrameMoved (newPosition);
+       BWindow::FrameMoved (newPosition);
+      }
   }
 
   void
   WorkspacesChanged (uint32_t old, uint32_t n)
   {
-    if (!child_frame_lock.Lock ())
-      gui_abort ("Failed to lock child frames for changing workspaces");
-    for (struct child_frame *f = subset_windows;
-        f; f = f->next)
-      DoUpdateWorkspace (f);
-    child_frame_lock.Unlock ();
+    CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK
+      {
+       for (struct child_frame *f = subset_windows;
+            f; f = f->next)
+         DoUpdateWorkspace (f);
+
+       child_frame_lock.Unlock ();
+      }
   }
 
   void



reply via email to

[Prev in Thread] Current Thread [Next in Thread]