diff options
| author | Po Lu | 2023-06-12 14:19:01 +0800 |
|---|---|---|
| committer | Po Lu | 2023-06-12 14:19:01 +0800 |
| commit | 3b08bb1318cd0bf6bc1811b520f9c6934b1aa3bd (patch) | |
| tree | b7effb4669608cb3329923a7c7a8a1387dbea412 | |
| parent | e3196835ed08a1d1a675b933a53d1a397defd561 (diff) | |
| download | emacs-3b08bb1318cd0bf6bc1811b520f9c6934b1aa3bd.tar.gz emacs-3b08bb1318cd0bf6bc1811b520f9c6934b1aa3bd.zip | |
Fix deadlocks
* java/org/gnu/emacs/EmacsView.java (EmacsView)
(showOnScreenKeyboard, hideOnScreenKeyboard): Don't synchronize.
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow)
(toggleOnScreenKeyboard): Revert to calling IMM functions from
the main thread.
* src/android.c (struct android_event_container)
(android_pselect_nfds, android_pselect_readfds)
(android_pselect_writefds, android_pselect_exceptfds)
(android_pselect_timeout): Don't make volatile.
(android_wait_event): Run queries if necessary.
| -rw-r--r-- | java/org/gnu/emacs/EmacsView.java | 5 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsWindow.java | 25 | ||||
| -rw-r--r-- | src/android.c | 30 |
3 files changed, 39 insertions, 21 deletions
diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java index 7fd672233f2..278c6025902 100644 --- a/java/org/gnu/emacs/EmacsView.java +++ b/java/org/gnu/emacs/EmacsView.java | |||
| @@ -590,16 +590,17 @@ public final class EmacsView extends ViewGroup | |||
| 590 | super.onAttachedToWindow (); | 590 | super.onAttachedToWindow (); |
| 591 | } | 591 | } |
| 592 | 592 | ||
| 593 | public synchronized void | 593 | public void |
| 594 | showOnScreenKeyboard () | 594 | showOnScreenKeyboard () |
| 595 | { | 595 | { |
| 596 | /* Specifying no flags at all tells the system the user asked for | 596 | /* Specifying no flags at all tells the system the user asked for |
| 597 | the input method to be displayed. */ | 597 | the input method to be displayed. */ |
| 598 | |||
| 598 | imManager.showSoftInput (this, 0); | 599 | imManager.showSoftInput (this, 0); |
| 599 | isCurrentlyTextEditor = true; | 600 | isCurrentlyTextEditor = true; |
| 600 | } | 601 | } |
| 601 | 602 | ||
| 602 | public synchronized void | 603 | public void |
| 603 | hideOnScreenKeyboard () | 604 | hideOnScreenKeyboard () |
| 604 | { | 605 | { |
| 605 | imManager.hideSoftInputFromWindow (this.getWindowToken (), | 606 | imManager.hideSoftInputFromWindow (this.getWindowToken (), |
diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index f5e40e9a2d9..68a18ec2aa7 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java | |||
| @@ -1201,16 +1201,25 @@ public final class EmacsWindow extends EmacsHandleObject | |||
| 1201 | } | 1201 | } |
| 1202 | 1202 | ||
| 1203 | public void | 1203 | public void |
| 1204 | toggleOnScreenKeyboard (boolean on) | 1204 | toggleOnScreenKeyboard (final boolean on) |
| 1205 | { | 1205 | { |
| 1206 | /* InputMethodManager functions are thread safe. Call | 1206 | /* Even though InputMethodManager functions are thread safe, |
| 1207 | `showOnScreenKeyboard' etc from the Emacs thread in order to | 1207 | `showOnScreenKeyboard' etc must be called from the UI thread in |
| 1208 | keep the calls in sync with updates to the input context. */ | 1208 | order to avoid deadlocks if the calls happen in tandem with a |
| 1209 | call to a synchronizing function within | ||
| 1210 | `onCreateInputConnection'. */ | ||
| 1209 | 1211 | ||
| 1210 | if (on) | 1212 | EmacsService.SERVICE.runOnUiThread (new Runnable () { |
| 1211 | view.showOnScreenKeyboard (); | 1213 | @Override |
| 1212 | else | 1214 | public void |
| 1213 | view.hideOnScreenKeyboard (); | 1215 | run () |
| 1216 | { | ||
| 1217 | if (on) | ||
| 1218 | view.showOnScreenKeyboard (); | ||
| 1219 | else | ||
| 1220 | view.hideOnScreenKeyboard (); | ||
| 1221 | } | ||
| 1222 | }); | ||
| 1214 | } | 1223 | } |
| 1215 | 1224 | ||
| 1216 | public String | 1225 | public String |
diff --git a/src/android.c b/src/android.c index 4414d465107..873d821361c 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -272,7 +272,7 @@ void *unused_pointer; | |||
| 272 | struct android_event_container | 272 | struct android_event_container |
| 273 | { | 273 | { |
| 274 | /* The next and last events in this queue. */ | 274 | /* The next and last events in this queue. */ |
| 275 | struct android_event_container *volatile next, *last; | 275 | struct android_event_container *next, *last; |
| 276 | 276 | ||
| 277 | /* The event itself. */ | 277 | /* The event itself. */ |
| 278 | union android_event event; | 278 | union android_event event; |
| @@ -301,11 +301,11 @@ struct android_event_queue | |||
| 301 | }; | 301 | }; |
| 302 | 302 | ||
| 303 | /* Arguments to pselect used by the select thread. */ | 303 | /* Arguments to pselect used by the select thread. */ |
| 304 | static volatile int android_pselect_nfds; | 304 | static int android_pselect_nfds; |
| 305 | static fd_set *volatile android_pselect_readfds; | 305 | static fd_set *android_pselect_readfds; |
| 306 | static fd_set *volatile android_pselect_writefds; | 306 | static fd_set *android_pselect_writefds; |
| 307 | static fd_set *volatile android_pselect_exceptfds; | 307 | static fd_set *android_pselect_exceptfds; |
| 308 | static struct timespec *volatile android_pselect_timeout; | 308 | static struct timespec *android_pselect_timeout; |
| 309 | 309 | ||
| 310 | /* Value of pselect. */ | 310 | /* Value of pselect. */ |
| 311 | static int android_pselect_rc; | 311 | static int android_pselect_rc; |
| @@ -569,12 +569,20 @@ android_pending (void) | |||
| 569 | return i; | 569 | return i; |
| 570 | } | 570 | } |
| 571 | 571 | ||
| 572 | /* Forward declaration. */ | ||
| 573 | |||
| 574 | static void android_check_query (void); | ||
| 575 | |||
| 572 | /* Wait for events to become available synchronously. Return once an | 576 | /* Wait for events to become available synchronously. Return once an |
| 573 | event arrives. */ | 577 | event arrives. Also, reply to the UI thread whenever it requires a |
| 578 | response. */ | ||
| 574 | 579 | ||
| 575 | void | 580 | void |
| 576 | android_wait_event (void) | 581 | android_wait_event (void) |
| 577 | { | 582 | { |
| 583 | /* Run queries from the UI thread to the Emacs thread. */ | ||
| 584 | android_check_query (); | ||
| 585 | |||
| 578 | pthread_mutex_lock (&event_queue.mutex); | 586 | pthread_mutex_lock (&event_queue.mutex); |
| 579 | 587 | ||
| 580 | /* Wait for events to appear if there are none available to | 588 | /* Wait for events to appear if there are none available to |
| @@ -584,6 +592,10 @@ android_wait_event (void) | |||
| 584 | &event_queue.mutex); | 592 | &event_queue.mutex); |
| 585 | 593 | ||
| 586 | pthread_mutex_unlock (&event_queue.mutex); | 594 | pthread_mutex_unlock (&event_queue.mutex); |
| 595 | |||
| 596 | /* Check for queries again. If a query is sent after the call to | ||
| 597 | `android_check_query' above, `read_var' will be signaled. */ | ||
| 598 | android_check_query (); | ||
| 587 | } | 599 | } |
| 588 | 600 | ||
| 589 | void | 601 | void |
| @@ -701,10 +713,6 @@ android_write_event (union android_event *event) | |||
| 701 | should answer the query ASAP. */ | 713 | should answer the query ASAP. */ |
| 702 | static bool android_urgent_query; | 714 | static bool android_urgent_query; |
| 703 | 715 | ||
| 704 | /* Forward declaration. */ | ||
| 705 | |||
| 706 | static void android_check_query (void); | ||
| 707 | |||
| 708 | int | 716 | int |
| 709 | android_select (int nfds, fd_set *readfds, fd_set *writefds, | 717 | android_select (int nfds, fd_set *readfds, fd_set *writefds, |
| 710 | fd_set *exceptfds, struct timespec *timeout) | 718 | fd_set *exceptfds, struct timespec *timeout) |