aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-04-14 13:14:32 +0000
committerPo Lu2022-04-14 13:14:32 +0000
commita9b8ebf34c97098631bf0f4a0fb254ff2f2d898d (patch)
tree7e061ccf981cec1ebb9068b6b58d5686664155ec /src
parente5ef0fe832a0514f83fea47fa16aab4b1a5d11a4 (diff)
downloademacs-a9b8ebf34c97098631bf0f4a0fb254ff2f2d898d.tar.gz
emacs-a9b8ebf34c97098631bf0f4a0fb254ff2f2d898d.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/haiku_support.cc52
1 files changed, 39 insertions, 13 deletions
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;
131static BLocker grab_view_locker; 131static BLocker grab_view_locker;
132static bool drag_and_drop_in_progress; 132static bool drag_and_drop_in_progress;
133 133
134/* Many places require us to lock the child frame data, and then lock
135 the locker of some random window. Unfortunately, locking such a
136 window might be delayed due to an arriving message, which then
137 calls a callback inside that window that tries to lock the child
138 frame data but doesn't finish since the child frame lock is already
139 held, not letting the code that held the child frame lock proceed,
140 thereby causing a deadlock.
141
142 Rectifying that problem is simple: all code in a looper callback
143 must lock the child frame data with this macro instead.
144
145 IOW, If some other code is already running with the child frame
146 lock held, don't interfere: wait until it's finished before
147 continuing. */
148#define CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK \
149 if (child_frame_lock.LockWithTimeout (200) != B_OK) \
150 { \
151 /* The Haiku equivalent of XPutBackEvent. */ \
152 if (CurrentMessage ()) \
153 PostMessage (CurrentMessage ()); \
154 } \
155 else
156
134/* This could be a private API, but it's used by (at least) the Qt 157/* This could be a private API, but it's used by (at least) the Qt
135 port, so it's probably here to stay. */ 158 port, so it's probably here to stay. */
136extern status_t get_subpixel_antialiasing (bool *); 159extern status_t get_subpixel_antialiasing (bool *);
@@ -968,25 +991,28 @@ public:
968 991
969 haiku_write (MOVE_EVENT, &rq); 992 haiku_write (MOVE_EVENT, &rq);
970 993
971 if (!child_frame_lock.Lock ()) 994 CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK
972 gui_abort ("Failed to lock child frame state lock"); 995 {
973 for (struct child_frame *f = subset_windows; 996 for (struct child_frame *f = subset_windows;
974 f; f = f->next) 997 f; f = f->next)
975 DoMove (f); 998 DoMove (f);
976 child_frame_lock.Unlock (); 999 child_frame_lock.Unlock ();
977 1000
978 BWindow::FrameMoved (newPosition); 1001 BWindow::FrameMoved (newPosition);
1002 }
979 } 1003 }
980 1004
981 void 1005 void
982 WorkspacesChanged (uint32_t old, uint32_t n) 1006 WorkspacesChanged (uint32_t old, uint32_t n)
983 { 1007 {
984 if (!child_frame_lock.Lock ()) 1008 CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK
985 gui_abort ("Failed to lock child frames for changing workspaces"); 1009 {
986 for (struct child_frame *f = subset_windows; 1010 for (struct child_frame *f = subset_windows;
987 f; f = f->next) 1011 f; f = f->next)
988 DoUpdateWorkspace (f); 1012 DoUpdateWorkspace (f);
989 child_frame_lock.Unlock (); 1013
1014 child_frame_lock.Unlock ();
1015 }
990 } 1016 }
991 1017
992 void 1018 void