2012-01-27 2 views
1

Введенный здесь код представляет собой попытку сопоставить SIGSEGV с исключением java. Прежде чем кто-то станет слишком взволнован, да, я знаю, это передает различные заявления в разных стандартах. Он предназначен как полностью временная тактика для отслеживания упрямой ошибки.throw, catch, sigaction macosx

На Mac, по крайней мере, он не работает. вызов C++ в вызове функции sigaction завершается.

Я отправляю этот вопрос, чтобы узнать, знает ли кто, как настроить это для работы.

#include <stdio.h> 
#include <signal.h> 
#include "com_github_bimargulies_jnisigsegv_Native.h" 

static JavaVM* staticJvm; 

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { 
    staticJvm = jvm; 
    return JNI_VERSION_1_6; 
} 

/* there has to be a catch. */ 
struct SomethingToThrow {}; 

void handler_function(int sig, struct __siginfo* si, void *) { 
    JNIEnv *env = 0; 
    staticJvm->GetEnv((void **)&env, JNI_VERSION_1_6); 
    jclass newExcCls = env->FindClass("java/lang/RuntimeException"); 
    env->ThrowNew(newExcCls, "SIGSEGV"); 
    fprintf(stderr, "About to throw at the catch ... block\n"); 
    fflush(stderr); 
    throw SomethingToThrow(); 
} 

JNIEXPORT void JNICALL Java_com_github_bimargulies_jnisigsegv_Native_setupHandler(JNIEnv *, jclass) { 

    struct sigaction sa; 
    struct sigaction oldsa; 
    sa.sa_sigaction = handler_function; 
    sa.sa_mask = 0; 
    sa.sa_flags = SA_SIGINFO; 
    int r = sigaction(SIGSEGV, &sa, &oldsa); 
    fprintf(stderr, "Signaction returned %d\n", r); 
    fflush(stderr); 
} 

JNIEXPORT void JNICALL Java_com_github_bimargulies_jnisigsegv_Native_getAnError 
(JNIEnv *, jclass, jstring) { 
    /* First experiment, just get a sigsegv */ 
    char * p = 0; 
    try { 
    *p = 1; 
    } catch (...) { 
    fprintf(stderr, "Caught something\n"); 
    } 
    return; 
} 

ответ

1

Посмотрите на родных битов ЮНА, который использует setjmp/longjmp, чтобы перевести SIGSEGV в исключения Java.

https://github.com/twall/jna/blob/master/native/protect.h

Обратите внимание, что когда вы начинаете добавлять свои собственные обработчики сигналов, вам необходимо правильно цепи сигналы обычно обрабатываются VM (см http://download.oracle.com/javase/6/docs/technotes/guides/vm/signal-chaining.html).

Вы должны внимательно прочитать страницы руководства для sigaction, чтобы просмотреть, что вы должны и не должны делать в обработчике сигналов. Есть только несколько системных вызовов, которые являются «безопасными», и я не помню, чтобы видеть что-либо о том, чтобы выбрасывать исключения C++ из контекста обработчика сигнала, который является поддерживаемой операцией. Вполне возможно, что ваша информация об исключении стека для C++ может быть недействительной или доступной в контексте обработчика сигналов.

+0

О, дорогой, я написал один из них с longjmp 15 лет назад. Это все-таки лучшее решение? Код в этом вопросе, кстати, работает для Linux. – bmargulies

+0

FWIW, реализация JNA работает на различных платформах, хотя она не является потокобезопасной (она использует статическую переменную для сохранения контекста, для потокобезопасного поведения она должна быть поточно-локальной). Поведение OSX показало бы, что ваш исключающий контекст * не * действителен в обработчике сигнала, поэтому _terminate() вызывается. – technomage