Моя цель состоит в том, чтобы в маловероятном сценарии возникновения одного из них я не завершал приложение.
p>
По сути, я следую подходу, который получил отсюда:
- В Application.onCreate я вызываю System.loadLibrary ( который вызывает JNI_OnLoad)
- В JNI_OnLoad я устанавливаю обработчики исключений (и сохраняю необходимые глобальные указатели классов)
- В Activity.onCreate я сохраняю Контекст действия и вызов собственного метода, который создаст рабочий поток.
- В рабочем потоке я пишу неверный код, который вызовет SIGSEGV или SIGFPE.
- Обработчик исключений запускается в том же рабочем потоке.
- В обработчике исключений я вызываю действие, которое покажет, что что-то пошло не так.
- Сообщите, что я вызываю обработчик исключений по умолчанию (как рекомендовано). Я также уничтожаю рабочий поток, чтобы исключить повторное возникновение исключений.
- Процесс завершается из-за вызова обработчика по умолчанию.
< li>Запущенное действие помечается как запускаемое в отдельном процессе (через файл манифеста) и, следовательно, не завершится после завершения первого процесса.
Код: Выделить всё
// MainApplication.kt
package com.example.exceptionhandling
import android.app.Application
import android.content.Context
import android.util.Log
class MainApplication : Application () {
override fun onCreate()
{
Log.d ("MyApp", "MainApplication.onCreate")
super.onCreate ()
System.loadLibrary ("exceptionhandling")
}
companion object {
public var sActivityCtx : Context? = null
}
}
Код: Выделить всё
// MainActivity.kt
package com.example.exceptionhandling
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.example.exceptionhandling.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override
fun onCreate (pSavedInstanceState: Bundle?)
{
Log.d ("MyApp", "MainActivity.onCreate")
super.onCreate (pSavedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
MainApplication.sActivityCtx = this
NativeMethod ()
}
override
fun onStop()
{
super.onStop()
Log.d ("MyApp", "MainActivity.onStop")
}
external fun NativeMethod () : Unit
}
Код: Выделить всё
// ExceptionActivity.kt
package com.example.exceptionhandling
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.example.exceptionhandling.databinding.ActivityMainBinding
class ExceptionActivity : AppCompatActivity () {
companion object {
// Invoked from C++
@JvmStatic
public fun StartExceptionActivity ()
{
Log.e ("MyApp", "Inside ExceptionActivity.StartExceptionActivity")
MainApplication.sActivityCtx!!.startActivity (Intent (MainApplication.sActivityCtx, ExceptionActivity::class.java))
}
}
public override
fun onCreate (pSavedInstanceState: Bundle?)
{
Log.d ("MyApp", "Inside ExceptionActivity.onCreate")
super.onCreate (pSavedInstanceState)
val linear_layout : LinearLayout
val textview : TextView?
linear_layout = LinearLayout (this)
textview = TextView (this)
textview.text = "Something has gone wrong!!"
linear_layout.addView (textview)
setContentView (linear_layout)
}
}
Код: Выделить всё
// native-lib.cpp
#include
#include
#include
#include
#include
#include
#define TRACE_LOG(x, ...) __android_log_print (ANDROID_LOG_DEBUG, "MyApp", x, ##__VA_ARGS__)
#define TRACEFUNC TRACE_LOG ("Inside %s", __PRETTY_FUNCTION__)
#define TRACELINE TRACE_LOG ("At line: %d", __LINE__)
JavaVM* gJavaVM;
jclass gExceptionActivityClass; // To store the class pointer of Exception Activity. Will be needed if its methods are to be invoked
thread_local JNIEnv * gThreadLocalEnv;
thread_local bool gIsWorkerThread {}; // Whether the thread is worker thread or main thread
using SignalHandlerFunc = void (*) (int, siginfo_t*, void *);
struct tSignals {
int uSignal;
SignalHandlerFunc uSignalHandlerFunc;
SignalHandlerFunc uDefaultSignalHandlerFunc;
};
void
ExceptionHandler (int pNum, siginfo_t *pInfo, void *pCtx) noexcept;
tSignals gSignals [] =
{
{SIGILL, ExceptionHandler, nullptr},
{SIGSEGV, ExceptionHandler, nullptr},
{SIGFPE, ExceptionHandler, nullptr},
};
void
ShouldNotGetCalled (int, siginfo_t*, void *) noexcept
{
TRACEFUNC;
}
SignalHandlerFunc
GetDefaultSignalHandlerFunc (int pSignal) noexcept
{
TRACEFUNC;
SignalHandlerFunc func = nullptr;
for (auto signal : gSignals) {
if (pSignal == signal.uSignal) {
func = signal.uDefaultSignalHandlerFunc;
break;
}
}
if (func)
return func;
return ShouldNotGetCalled;
}
void
StartExceptionActivity () noexcept
{
TRACEFUNC;
jmethodID method_id;
method_id = gThreadLocalEnv->GetStaticMethodID (gExceptionActivityClass, "StartExceptionActivity", "()V");
if (method_id == NULL) {
TRACELINE;
return;
}
gThreadLocalEnv->CallStaticVoidMethod (gExceptionActivityClass, method_id);
TRACELINE;
}
void
AttachThread () noexcept
{
TRACEFUNC;
gJavaVM->GetEnv ((void **) &gThreadLocalEnv, JNI_VERSION_1_6);
gJavaVM->AttachCurrentThread (&gThreadLocalEnv, nullptr);
}
void
DetachThread () noexcept
{
TRACEFUNC;
gJavaVM->DetachCurrentThread ();
}
[[noreturn]]
void
KillThread () noexcept
{
TRACEFUNC;
DetachThread ();
pthread_exit (nullptr);
}
void
ExceptionHandler (int pNum, siginfo_t* pInfo, void * pCtx) noexcept
{
TRACEFUNC;
TRACE_LOG ("Exception number = %d", pNum);
StartExceptionActivity();
GetDefaultSignalHandlerFunc (pNum) (pNum, pInfo, pCtx);
if (gIsWorkerThread)
KillThread ();
}
void
SetExceptionHandlers () noexcept
{
TRACEFUNC;
struct sigaction sa {};
struct sigaction sa_out {};
// SIGACTION Register
sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
for (auto & signal : gSignals) {
sa.sa_sigaction = signal.uSignalHandlerFunc;
sigaction (signal.uSignal, &sa, &sa_out);
signal.uDefaultSignalHandlerFunc = sa_out.sa_sigaction;
TRACE_LOG ("Default handler = %p\n", signal.uDefaultSignalHandlerFunc);
}
TRACE_LOG ("ExceptionHandler Set");
}
extern "C" JNIEXPORT jint JNICALL
JNI_OnLoad (JavaVM * pJavaVM, [[maybe_unused]] void * pReserved)
{
TRACEFUNC;
jclass exception_activity_class;
JNIEnv * env;
gJavaVM = pJavaVM;
gIsWorkerThread = false;
if (pJavaVM->GetEnv ((void **) &env, JNI_VERSION_1_6) != JNI_OK)
return JNI_ERR;
exception_activity_class = env->FindClass ("com/example/exceptionhandling/ExceptionActivity");
if (exception_activity_class == nullptr) {
TRACELINE;
return JNI_ERR;
}
gExceptionActivityClass = (jclass) env->NewGlobalRef (exception_activity_class);
SetExceptionHandlers ();
return JNI_VERSION_1_6;
}
void
RaiseException () noexcept
{
TRACEFUNC;
int a = 5;
int b = 0;
int c;
c = a / b;
TRACE_LOG ("Num = %d", c);
}
void *
ThreadFunc (void* ) noexcept
{
TRACEFUNC;
gIsWorkerThread = true;
AttachThread ();
RaiseException ();
TRACELINE;
return nullptr;
}
// Invoked from MainActivity.onCreate
extern "C" JNIEXPORT void JNICALL
Java_com_example_exceptionhandling_MainActivity_NativeMethod (JNIEnv* pEnv, jobject pObject)
{
TRACEFUNC;
pthread_t thread_handle;
pthread_create (&thread_handle, nullptr, ThreadFunc, nullptr);
}
ExceptionActivity запускается в своем собственном процессе, а первый процесс затухает. Я получаю следующие журналы:
Код: Выделить всё
---------------------------- PROCESS STARTED (4523) for package com.example.exceptionhandling ----------------------------
2024-04-09 20:02:16.117 4523-4523 MyApp com.example.exceptionhandling D MainApplication.onCreate
2024-04-09 20:02:16.120 4523-4523 MyApp com.example.exceptionhandling D Inside jint JNI_OnLoad(JavaVM *, void *)
2024-04-09 20:02:16.144 4523-4523 MyApp com.example.exceptionhandling D Inside void SetExceptionHandlers()
2024-04-09 20:02:16.147 4523-4523 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 20:02:16.149 4523-4523 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 20:02:16.149 4523-4523 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 20:02:16.152 4523-4523 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 20:02:16.152 4523-4523 MyApp com.example.exceptionhandling D ExceptionHandler Set
2024-04-09 20:02:16.807 4523-4523 MyApp com.example.exceptionhandling D MainActivity.onCreate
2024-04-09 20:02:17.922 4523-4523 MyApp com.example.exceptionhandling D Inside void Java_com_example_exceptionhandling_MainActivity_NativeMethod(JNIEnv *, jobject)
2024-04-09 20:02:17.923 4523-4523 MyApp com.example.exceptionhandling D Inside void CreateThread()
2024-04-09 20:02:17.925 4523-4604 MyApp com.example.exceptionhandling D Inside void *ThreadFunc(void *)
2024-04-09 20:02:17.925 4523-4604 MyApp com.example.exceptionhandling D Inside void AttachThread()
2024-04-09 20:02:17.925 4523-4604 MyApp com.example.exceptionhandling D Inside void RaiseException()
2024-04-09 20:02:17.925 4523-4604 MyApp com.example.exceptionhandling D Inside void ExceptionHandler(int, siginfo_t *, void *)
2024-04-09 20:02:17.925 4523-4604 MyApp com.example.exceptionhandling D Exception number = 8
2024-04-09 20:02:17.925 4523-4604 MyApp com.example.exceptionhandling D Inside void StartExceptionActivity()
2024-04-09 20:02:17.967 4523-4604 MyApp com.example.exceptionhandling D At line: 46
2024-04-09 20:02:17.967 4523-4604 MyApp com.example.exceptionhandling D Inside SignalHandlerFunc GetDefaultSignalHandlerFunc(int)
---------------------------- PROCESS STARTED (4606) for package com.example.exceptionhandling ----------------------------
---------------------------- PROCESS STARTED (4616) for package com.example.exceptionhandling ----------------------------
2024-04-09 20:02:18.420 4523-4604 MyApp com.example.exceptionhandling D Inside void KillThread()
2024-04-09 20:02:18.420 4523-4604 MyApp com.example.exceptionhandling D Inside void DetachThread()
2024-04-09 20:02:18.580 4606-4606 MyApp com.example.exceptionhandling D MainApplication.onCreate
2024-04-09 20:02:18.597 4606-4606 MyApp com.example.exceptionhandling D Inside jint JNI_OnLoad(JavaVM *, void *)
2024-04-09 20:02:18.635 4606-4606 MyApp com.example.exceptionhandling D Inside void SetExceptionHandlers()
2024-04-09 20:02:18.636 4606-4606 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 20:02:18.637 4606-4606 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 20:02:18.637 4606-4606 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 20:02:18.638 4606-4606 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 20:02:18.638 4606-4606 MyApp com.example.exceptionhandling D ExceptionHandler Set
2024-04-09 20:02:18.825 4523-4523 MyApp com.example.exceptionhandling D MainActivity.onStop
2024-04-09 20:02:19.181 4606-4606 MyApp com.example.exceptionhandling D Inside ExceptionActivity.onCreate
---------------------------- PROCESS ENDED (4616) for package com.example.exceptionhandling ----------------------------
Теперь, если я изменю логику функции RaiseException (которая вызывается в рабочем потоке), чтобы вызвать SIGSEGV, дела идут наперекосяк

Код: Выделить всё
// native-lib.cpp
void
RaiseException () noexcept
{
TRACEFUNC;
int * ptr = nullptr;
*ptr = 45;
TRACE_LOG ("Num = %d", *ptr);
}
Строка, вызывающая это, — это CallStaticVoidMethod, которая вызвала StartExceptionActivity в Kotlin. Он выдает кучу исключений, когда пытается startActivity запустить ExceptionActivity. Это происходит несколько раз, а потом все умирает.
Код: Выделить всё
---------------------------- PROCESS STARTED (1678) for package com.example.exceptionhandling ----------------------------
2024-04-09 19:49:49.729 1678-1678 MyApp com.example.exceptionhandling D MainApplication.onCreate
2024-04-09 19:49:49.731 1678-1678 MyApp com.example.exceptionhandling D Inside jint JNI_OnLoad(JavaVM *, void *)
2024-04-09 19:49:49.767 1678-1678 MyApp com.example.exceptionhandling D Inside void SetExceptionHandlers()
2024-04-09 19:49:49.767 1678-1678 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 19:49:49.767 1678-1678 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 19:49:49.767 1678-1678 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 19:49:49.768 1678-1678 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 19:49:49.775 1678-1678 MyApp com.example.exceptionhandling D ExceptionHandler Set
2024-04-09 19:49:50.709 1678-1678 MyApp com.example.exceptionhandling D MainActivity.onCreate
2024-04-09 19:49:51.497 1678-1678 MyApp com.example.exceptionhandling D Inside void Java_com_example_exceptionhandling_MainActivity_NativeMethod(JNIEnv *, jobject)
2024-04-09 19:49:51.497 1678-1678 MyApp com.example.exceptionhandling D Inside void CreateThread()
2024-04-09 19:49:51.499 1678-1758 MyApp com.example.exceptionhandling D Inside void *ThreadFunc(void *)
2024-04-09 19:49:51.499 1678-1758 MyApp com.example.exceptionhandling D Inside void AttachThread()
2024-04-09 19:49:51.499 1678-1758 MyApp com.example.exceptionhandling D Inside void RaiseException()
2024-04-09 19:49:51.499 1678-1758 MyApp com.example.exceptionhandling D Inside void ExceptionHandler(int, siginfo_t *, void *)
2024-04-09 19:49:51.499 1678-1758 MyApp com.example.exceptionhandling D Exception number = 11
2024-04-09 19:49:51.499 1678-1758 MyApp com.example.exceptionhandling D Inside void StartExceptionActivity()
2024-04-09 19:49:51.839 1678-1758 MyApp com.example.exceptionhandling D Inside void ExceptionHandler(int, siginfo_t *, void *)
2024-04-09 19:49:51.839 1678-1758 MyApp com.example.exceptionhandling D Exception number = 6
2024-04-09 19:49:51.839 1678-1758 MyApp com.example.exceptionhandling D Inside void StartExceptionActivity()
---------------------------- PROCESS ENDED (1678) for package com.example.exceptionhandling ----------------------------
---------------------------- PROCESS STARTED (1759) for package com.example.exceptionhandling ----------------------------
2024-04-09 19:49:52.588 1759-1759 MyApp com.example.exceptionhandling D MainApplication.onCreate
2024-04-09 19:49:52.591 1759-1759 MyApp com.example.exceptionhandling D Inside jint JNI_OnLoad(JavaVM *, void *)
2024-04-09 19:49:52.603 1759-1759 MyApp com.example.exceptionhandling D Inside void SetExceptionHandlers()
2024-04-09 19:49:52.604 1759-1759 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 19:49:52.604 1759-1759 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 19:49:52.604 1759-1759 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 19:49:52.604 1759-1759 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 19:49:52.604 1759-1759 MyApp com.example.exceptionhandling D ExceptionHandler Set
2024-04-09 19:49:52.967 1759-1759 MyApp com.example.exceptionhandling D MainActivity.onCreate
2024-04-09 19:49:53.767 1759-1759 MyApp com.example.exceptionhandling D Inside void Java_com_example_exceptionhandling_MainActivity_NativeMethod(JNIEnv *, jobject)
2024-04-09 19:49:53.767 1759-1759 MyApp com.example.exceptionhandling D Inside void CreateThread()
2024-04-09 19:49:53.771 1759-1788 MyApp com.example.exceptionhandling D Inside void *ThreadFunc(void *)
2024-04-09 19:49:53.771 1759-1788 MyApp com.example.exceptionhandling D Inside void AttachThread()
2024-04-09 19:49:53.771 1759-1788 MyApp com.example.exceptionhandling D Inside void RaiseException()
2024-04-09 19:49:53.771 1759-1788 MyApp com.example.exceptionhandling D Inside void ExceptionHandler(int, siginfo_t *, void *)
2024-04-09 19:49:53.771 1759-1788 MyApp com.example.exceptionhandling D Exception number = 11
2024-04-09 19:49:53.771 1759-1788 MyApp com.example.exceptionhandling D Inside void StartExceptionActivity()
2024-04-09 19:49:54.110 1759-1788 MyApp com.example.exceptionhandling D Inside void ExceptionHandler(int, siginfo_t *, void *)
2024-04-09 19:49:54.110 1759-1788 MyApp com.example.exceptionhandling D Exception number = 6
2024-04-09 19:49:54.110 1759-1788 MyApp com.example.exceptionhandling D Inside void StartExceptionActivity()
---------------------------- PROCESS ENDED (1759) for package com.example.exceptionhandling ----------------------------
---------------------------- PROCESS STARTED (1789) for package com.example.exceptionhandling ----------------------------
2024-04-09 19:49:54.911 1789-1789 MyApp com.example.exceptionhandling D MainApplication.onCreate
2024-04-09 19:49:54.912 1789-1789 MyApp com.example.exceptionhandling D Inside jint JNI_OnLoad(JavaVM *, void *)
2024-04-09 19:49:54.927 1789-1789 MyApp com.example.exceptionhandling D Inside void SetExceptionHandlers()
2024-04-09 19:49:54.928 1789-1789 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 19:49:54.928 1789-1789 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 19:49:54.928 1789-1789 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 19:49:54.929 1789-1789 MyApp com.example.exceptionhandling D Default handler = 0x7395f2d1ab91
2024-04-09 19:49:54.929 1789-1789 MyApp com.example.exceptionhandling D ExceptionHandler Set
2024-04-09 19:49:55.585 1789-1789 MyApp com.example.exceptionhandling D MainActivity.onCreate
2024-04-09 19:49:56.296 1789-1789 MyApp com.example.exceptionhandling D Inside void Java_com_example_exceptionhandling_MainActivity_NativeMethod(JNIEnv *, jobject)
2024-04-09 19:49:56.296 1789-1789 MyApp com.example.exceptionhandling D Inside void CreateThread()
2024-04-09 19:49:56.296 1789-1840 MyApp com.example.exceptionhandling D Inside void *ThreadFunc(void *)
2024-04-09 19:49:56.297 1789-1840 MyApp com.example.exceptionhandling D Inside void AttachThread()
2024-04-09 19:49:56.297 1789-1840 MyApp com.example.exceptionhandling D Inside void RaiseException()
2024-04-09 19:49:56.297 1789-1840 MyApp com.example.exceptionhandling D Inside void ExceptionHandler(int, siginfo_t *, void *)
2024-04-09 19:49:56.297 1789-1840 MyApp com.example.exceptionhandling D Exception number = 11
2024-04-09 19:49:56.297 1789-1840 MyApp com.example.exceptionhandling D Inside void StartExceptionActivity()
2024-04-09 19:49:56.783 1789-1840 MyApp com.example.exceptionhandling D Inside void ExceptionHandler(int, siginfo_t *, void *)
2024-04-09 19:49:56.783 1789-1840 MyApp com.example.exceptionhandling D Exception number = 6
2024-04-09 19:49:56.783 1789-1840 MyApp com.example.exceptionhandling D Inside void StartExceptionActivity()
---------------------------- PROCESS ENDED (1789) for package com.example.exceptionhandling ----------------------------
Код: Выделить всё
2024-04-09 19:57:50.419 1928-1956 MyApp com.example.exceptionhandling D Inside void StartExceptionActivity()
2024-04-09 19:57:50.424 1928-1956 ceptionhandling com.example.exceptionhandling A java_vm_ext.cc:591] JNI DETECTED ERROR IN APPLICATION: JNI ERROR (app bug): jobject is an invalid JNI transition frame reference: 0x7395e30c9d20 (use of invalid jobject)
java_vm_ext.cc:591] in call to IsInstanceOf
java_vm_ext.cc:591] from void android.os.Parcel.nativeMarkForBinder(long, android.os.IBinder)
Мои вопросы:
Мои вопросы:
p>
- Почему это происходит только с SIGSEGV, а не с другими? Несмотря на то, что обработчики по умолчанию для них одинаковы (как видно из журналов).
- Есть ли способ решить эту проблему?
- Если нет , смогу ли я когда-нибудь справиться с SIGSEGV?
Подробнее здесь: https://stackoverflow.com/questions/782 ... in-android