diff options
| author | Po Lu | 2022-04-14 13:14:32 +0000 |
|---|---|---|
| committer | Po Lu | 2022-04-14 13:14:32 +0000 |
| commit | a9b8ebf34c97098631bf0f4a0fb254ff2f2d898d (patch) | |
| tree | 7e061ccf981cec1ebb9068b6b58d5686664155ec /src | |
| parent | e5ef0fe832a0514f83fea47fa16aab4b1a5d11a4 (diff) | |
| download | emacs-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.cc | 52 |
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; | |||
| 131 | static BLocker grab_view_locker; | 131 | static BLocker grab_view_locker; |
| 132 | static bool drag_and_drop_in_progress; | 132 | static 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. */ |
| 136 | extern status_t get_subpixel_antialiasing (bool *); | 159 | extern 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 |