Код: Выделить всё
// ExceptionHandlingCpp.h file
using SignalHandlerFunc = void (*) (int, siginfo_t *, void *);
struct tSignals {
SignalHandlerFunc signalHandlerFunc;
uint32_t signal;
[[maybe_unused]]
uint8_t reserved[4];
};
class ExceptionHandlingCpp {
public:
static tSignals unixSignals[];
private:
static uint8_t numOfRecursions;
static thread_local uint8_t currentIteration;
// Other private data members
public:
static void RegisterSignals();
static void HandleSignals(int pSignals, siginfo_t* pInfo, void* pContext);
static void UnregisterSignal(int pSignal);
static void CheckRecursiveExceptions(int pSignal);
static void* DivisionByZero(void* pParms);
// Other public member functions
};
Код: Выделить всё
// ExceptionHandlingCpp.cpp file
tSignals ExceptionHandlingCpp::unixSignals[] = {
{HandleSignals, SIGFPE, {0}},
{HandleSignals, SIGSEGV, {0}},
{HandleSignals, SIGKILL, {0}},
};
uint8_t ExceptionHandlingCpp::numOfRecursions {5};
thread_local uint8_t ExceptionHandlingCpp::currentIteration {0};
void ExceptionHandlingCpp::RegisterSignals() {
LOG("ExceptionHandlingCpp::RegisterSignals()");
struct sigaction sa;
sa.sa_flags = SA_SIGINFO;
for(int i = 0; i < sizeof(unixSignals)/sizeof(tSignals); ++i) {
sa.sa_sigaction = unixSignals[i].signalHandlerFunc;
sigaction(unixSignals[i].signal, &sa, nullptr);
}
}
void ExceptionHandlingCpp::HandleSignals(int pSignal, siginfo_t *pInfo, void *pContext) {
LOG("ExceptionHandlingCpp::HandleSignals(int, signinfo_t*, void*)");
LOG("signal = " + signalName(pSignal));
// TODO: Handle the exception/signal.
// Sets the default handler if the exception keeps repeating
// more than 5 times. This is just to experiment what happens when
// the default handler is set for the signal.
CheckRecursiveExceptions(pSignal);
// Record the exception count
LOG("currentIteration = " + std::to_string(currentIteration));
LOG("Returning from exception handler...");
}
void ExceptionHandlingCpp::UnregisterSignal(int pSignal) {
LOG("ExceptionHandlingCpp::UnregisterSignal(int)");
struct sigaction defaultAction {};
defaultAction.sa_handler = SIG_DFL;
if(sigaction(pSignal, &defaultAction, nullptr) == -1) {
LOG("Error in resetting action for " + signalName(pSignal));
} else {
LOG("Successfully reset " + signalName(pSignal) + "'s action to default!");
}
}
void ExceptionHandlingCpp::CheckRecursiveExceptions(int pSignal) {
LOG("ExceptionHandlingCpp::CheckRecursiveExceptions()");
currentIteration++;
if(currentIteration > numOfRecursions) {
// After repeating for said times, update the action for the signal to default and do nothing
UnregisterSignal(pSignal);
} else {
LOG("Number of recursions so far = " + std::to_string(currentIteration));
}
}
void* ExceptionHandlingCpp::DivisionByZero ([[maybe_unused]] void* pParms)
{
LOG("ExceptionHandlingCpp::DivisionByZero()");
int num1;
int num2;
int result;
num1 = 5;
num2 = 0;
LOG("Raising exception...");
result = num1 / num2;
LOG("Returning from DivisionByZero() method");
return nullptr;
}
std::string ExceptionHandlingCpp::signalName(int pSignal)
{
switch(pSignal) {
case SIGSEGV:
return "SIGSEGV";
case SIGFPE:
return "SIGFPE";
case SIGKILL:
return "SIGKILL";
default:
return "Undefined signal!";
}
}
Код: Выделить всё
SIGSEGVКод: Выделить всё
HandleSignalsВ logcat есть следующие журналы:
Код: Выделить всё
---------------------------- PROCESS STARTED (6199) for package sample.experiments.androidexceptionhandling ----------------------------
(2 | 6199) MainApplication.onCreate()
(6199) JNI_OnLoad(JavaVM*, void*)
(6199) Initializing JavaVM...
(2 | 6199) MainActivity.onCreate(Bundle?)
(6199) Java_sample_experiments_androidexceptionhandling_KotlinExceptions_testExceptionHandlerFromCpp(JNIEnv *, jobject)
(6199) ExceptionHandlingCpp::RegisterSignals()
(6199) TestExceptionHandler()
(6199) ***** Begin Exception Handling testing (C++) *****
(6199) ExceptionHandlingCpp::DivisionByZero()
(6199) Raising exception...
(6199) ExceptionHandlingCpp::HandleSignals(int, signinfo_t*, void*)
(6199) signal = SIGFPE
(6199) ExceptionHandlingCpp::CheckRecursiveExceptions()
(6199) Number of recursions so far = 1
(6199) Returning from exception handler...
(6199) ExceptionHandlingCpp::HandleSignals(int, signinfo_t*, void*)
(6199) signal = SIGFPE
(6199) ExceptionHandlingCpp::CheckRecursiveExceptions()
(6199) Number of recursions so far = 2
(6199) Returning from exception handler...
(6199) ExceptionHandlingCpp::HandleSignals(int, signinfo_t*, void*)
(6199) signal = SIGFPE
(6199) ExceptionHandlingCpp::CheckRecursiveExceptions()
(6199) Number of recursions so far = 3
(6199) Returning from exception handler...
(6199) ExceptionHandlingCpp::HandleSignals(int, signinfo_t*, void*)
(6199) signal = SIGFPE
(6199) ExceptionHandlingCpp::CheckRecursiveExceptions()
(6199) Number of recursions so far = 4
(6199) Returning from exception handler...
(6199) ExceptionHandlingCpp::HandleSignals(int, signinfo_t*, void*)
(6199) signal = SIGFPE
(6199) ExceptionHandlingCpp::CheckRecursiveExceptions()
(6199) Number of recursions so far = 5
(6199) Returning from exception handler...
(6199) ExceptionHandlingCpp::HandleSignals(int, signinfo_t*, void*)
(6199) signal = SIGFPE
(6199) ExceptionHandlingCpp::CheckRecursiveExceptions()
(6199) ExceptionHandlingCpp::UnregisterSignal(int)
(6199) Successfully reset SIGFPE's action to default!
(6199) Returning from exception handler...
---------------------------- PROCESS ENDED (6199) for package sample.experiments.androidexceptionhandling ----------------------------
---------------------------- PROCESS STARTED (6276) for package sample.experiments.androidexceptionhandling ----------------------------
(2 | 6276) MainApplication.onCreate()
(6276) JNI_OnLoad(JavaVM*, void*)
(6276) Initializing JavaVM...
(2 | 6276) MainActivity.onCreate(Bundle?)
(6276) Java_sample_experiments_androidexceptionhandling_KotlinExceptions_testExceptionHandlerFromCpp(JNIEnv *, jobject)
(6276) ExceptionHandlingCpp::RegisterSignals()
(6276) TestExceptionHandler()
(6276) ***** Begin Exception Handling testing (C++) *****
(6276) ExceptionHandlingCpp::DivisionByZero()
(6276) Raising exception...
(6276) ExceptionHandlingCpp::HandleSignals(int, signinfo_t*, void*)
(6276) signal = SIGFPE
Когда я прекращаю регистрацию для FPE, процесс завершается, как и ожидалось.
Почему процесс продолжает перезапускаться? Я ожидаю, что процесс завершится после установки обработчика по умолчанию. Это какая-то настройка студии Android? Я обновил Android Studio, несколько раз удалял и воссоздавал проект, пробовал использовать разные эмуляторы, но ничего не помогло.
Среда:
Студийная версия Android: Ladybug
Операционная система эмулятора: Android 13.0 (Тирамису) и Android 14.0 (перевернутый торт)
Подробнее здесь: https://stackoverflow.com/questions/791 ... -exception
Мобильная версия