From c321eea5af535d102c5e1d2d7e95029ce6fee427 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Fri, 9 Jun 2023 14:03:50 +0800 Subject: [PATCH] Block profiling signals in the Android UI thread * java/org/gnu/emacs/EmacsNative.java (EmacsNative): New function `setupSystemThread'. * java/org/gnu/emacs/EmacsService.java (onCreate): Block all signals except for SIGBUS and SIGSEGV in the UI thread. * src/android.c (setupSystemThread): New function. --- java/org/gnu/emacs/EmacsNative.java | 4 ++++ java/org/gnu/emacs/EmacsService.java | 25 +++++++++++++++++++++++++ src/android.c | 24 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java index cb89cf6808a..2fcbf8b94ef 100644 --- a/java/org/gnu/emacs/EmacsNative.java +++ b/java/org/gnu/emacs/EmacsNative.java @@ -188,6 +188,10 @@ public final class EmacsNative KEYCODE_VOLUME_MUTE should be forwarded to Emacs. */ public static native boolean shouldForwardMultimediaButtons (); + /* Initialize the current thread, by blocking signals that do not + interest it. */ + public static native void setupSystemThread (); + /* Input connection functions. These mostly correspond to their diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java index 48e39f8b355..96216e51cf4 100644 --- a/java/org/gnu/emacs/EmacsService.java +++ b/java/org/gnu/emacs/EmacsService.java @@ -25,6 +25,7 @@ import java.io.UnsupportedEncodingException; import java.util.List; +import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; import android.graphics.Matrix; @@ -211,6 +212,7 @@ public final class EmacsService extends Service final String filesDir, libDir, cacheDir, classPath; final double pixelDensityX; final double pixelDensityY; + final Semaphore signalSemaphore; SERVICE = this; handler = new Handler (Looper.getMainLooper ()); @@ -220,6 +222,7 @@ public final class EmacsService extends Service pixelDensityX = metrics.xdpi; pixelDensityY = metrics.ydpi; resolver = getContentResolver (); + signalSemaphore = new Semaphore (0); try { @@ -248,11 +251,33 @@ public final class EmacsService extends Service cacheDir, (float) pixelDensityX, (float) pixelDensityY, classPath, EmacsService.this); + + /* Wait for the signal mask to be set up in the UI + thread. */ + + while (true) + { + try + { + signalSemaphore.acquire (); + break; + } + catch (InterruptedException e) + { + ;; + } + } } }, extraStartupArgument, /* If any file needs to be opened, open it now. */ EmacsOpenActivity.fileToOpen); thread.start (); + + /* Now that the thread has been started, block signals which + don't interest the current thread. */ + + EmacsNative.setupSystemThread (); + signalSemaphore.release (); } catch (IOException exception) { diff --git a/src/android.c b/src/android.c index 92aab548180..681723124ee 100644 --- a/src/android.c +++ b/src/android.c @@ -3077,6 +3077,30 @@ NATIVE_NAME (answerQuerySpin) (JNIEnv *env, jobject object) android_answer_query_spin (); } + + +/* System thread setup. Android doesn't always block signals Emacs is + interested in from being received by the UI or render threads, + which can lead to problems when those signals then interrupt one of + those threads. */ + +JNIEXPORT void JNICALL +NATIVE_NAME (setupSystemThread) (void) +{ + sigset_t sigset; + + /* Block everything except for SIGSEGV and SIGBUS; those two are + used by the runtime. */ + + sigfillset (&sigset); + sigaddset (&sigset, SIGSEGV); + sigaddset (&sigset, SIGBUS); + + if (pthread_sigmask (SIG_BLOCK, &sigset, NULL)) + __android_log_print (ANDROID_LOG_WARN, __func__, + "pthread_sigmask: %s", strerror (errno)); +} + #ifdef __clang__ #pragma clang diagnostic pop #else -- 2.39.2