From: Po Lu Date: Thu, 14 Apr 2022 13:14:32 +0000 (+0000) Subject: Fix races with child frame locks on Haiku X-Git-Tag: emacs-29.0.90~1931^2~578 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=a9b8ebf34c97098631bf0f4a0fb254ff2f2d898d;p=emacs.git 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. --- diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 599ff305ae3..f0db852e26e 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