Reputation: 7106
I have the following CPP code. What I want to do is when an error occurs in my native side, I will notify Java about the error. I used How can I catch SIGSEGV (segmentation fault) and get a stack trace under JNI on Android? as reference.
static JavaVM* g_JVM = NULL;
static jobject g_thejavaobject = NULL;
void InitializeNativeSide(JNIEnv *env, jclass, jobject object)
{
env->GetJavaVM(&g_JVM);
g_thejavaobject = env->NewGlobalRef(object);
}
// this executes in another thread running in parallel with UI thread
void StartExecuting(JNIEnv *_env, jclass) {
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = SignalErrorHandler;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &sa, NULL);
// native starts executing here. after a while, a SEGFAULT is encountered
// triggering SignalErrorHandler()
...
}
void SignalErrorHandler(int signal, siginfo_t *si, void *arg)
{
JNIEnv *env;
g_JVM->GetEnv((void**)&env, JNI_VERSION_1_6);
jclass myClass = env->FindClass("com/company/MyClass");
jmethodID myMethod = env->GetMethodID(myClass, "nativeCrashed", "()V" );
env->CallVoidMethod(g_thejavaobject, myMethod);
env->DeleteLocalRef(myClass);
}
Everything works fine but the call to myClass.nativeCrashed() does not work. What am I doing wrong?
Upvotes: 1
Views: 456
Reputation: 1
You can't do this:
void SignalErrorHandler(int signal, siginfo_t *si, void *arg)
{
JNIEnv *env;
g_JVM->GetEnv((void**)&env, JNI_VERSION_1_6);
jclass myClass = env->FindClass("com/company/MyClass");
jmethodID myMethod = env->GetMethodID(myClass, "nativeCrashed", "()V" );
env->CallVoidMethod(g_thejavaobject, myMethod);
env->DeleteLocalRef(myClass);
}
That will not work for at least two fundamental reasons.
First, only async-signal-safe functions may be called from within a signal handler. The POSIX-specified list can be found at http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03.
No Java JNI call is async-signal-safe.
Second, the Java JVM uses SIGSEGV
internally - getting a SIGSEGV
is not necessarily fatal:
Signals Used in Oracle Solaris, Linux, and macOS
...
SIGSEGV, SIGBUS, SIGFPE, SIGPIPE, SIGILL
These signals are used in the implementation for implicit null check, and so forth.
Upvotes: 2