From 3b08bb1318cd0bf6bc1811b520f9c6934b1aa3bd Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 12 Jun 2023 14:19:01 +0800 Subject: [PATCH] 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. --- java/org/gnu/emacs/EmacsView.java | 5 +++-- java/org/gnu/emacs/EmacsWindow.java | 25 ++++++++++++++++-------- 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 super.onAttachedToWindow (); } - public synchronized void + public void showOnScreenKeyboard () { /* Specifying no flags at all tells the system the user asked for the input method to be displayed. */ + imManager.showSoftInput (this, 0); isCurrentlyTextEditor = true; } - public synchronized void + public void hideOnScreenKeyboard () { 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 } public void - toggleOnScreenKeyboard (boolean on) + toggleOnScreenKeyboard (final boolean on) { - /* InputMethodManager functions are thread safe. Call - `showOnScreenKeyboard' etc from the Emacs thread in order to - keep the calls in sync with updates to the input context. */ + /* Even though InputMethodManager functions are thread safe, + `showOnScreenKeyboard' etc must be called from the UI thread in + order to avoid deadlocks if the calls happen in tandem with a + call to a synchronizing function within + `onCreateInputConnection'. */ - if (on) - view.showOnScreenKeyboard (); - else - view.hideOnScreenKeyboard (); + EmacsService.SERVICE.runOnUiThread (new Runnable () { + @Override + public void + run () + { + if (on) + view.showOnScreenKeyboard (); + else + view.hideOnScreenKeyboard (); + } + }); } 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; struct android_event_container { /* The next and last events in this queue. */ - struct android_event_container *volatile next, *last; + struct android_event_container *next, *last; /* The event itself. */ union android_event event; @@ -301,11 +301,11 @@ struct android_event_queue }; /* Arguments to pselect used by the select thread. */ -static volatile int android_pselect_nfds; -static fd_set *volatile android_pselect_readfds; -static fd_set *volatile android_pselect_writefds; -static fd_set *volatile android_pselect_exceptfds; -static struct timespec *volatile android_pselect_timeout; +static int android_pselect_nfds; +static fd_set *android_pselect_readfds; +static fd_set *android_pselect_writefds; +static fd_set *android_pselect_exceptfds; +static struct timespec *android_pselect_timeout; /* Value of pselect. */ static int android_pselect_rc; @@ -569,12 +569,20 @@ android_pending (void) return i; } +/* Forward declaration. */ + +static void android_check_query (void); + /* Wait for events to become available synchronously. Return once an - event arrives. */ + event arrives. Also, reply to the UI thread whenever it requires a + response. */ void android_wait_event (void) { + /* Run queries from the UI thread to the Emacs thread. */ + android_check_query (); + pthread_mutex_lock (&event_queue.mutex); /* Wait for events to appear if there are none available to @@ -584,6 +592,10 @@ android_wait_event (void) &event_queue.mutex); pthread_mutex_unlock (&event_queue.mutex); + + /* Check for queries again. If a query is sent after the call to + `android_check_query' above, `read_var' will be signaled. */ + android_check_query (); } void @@ -701,10 +713,6 @@ android_write_event (union android_event *event) should answer the query ASAP. */ static bool android_urgent_query; -/* Forward declaration. */ - -static void android_check_query (void); - int android_select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timespec *timeout) -- 2.39.2