2012-01-27 4 views
1

ここに貼り付けられたコードは、SIGSEGVをJava例外にマップする試みです。誰もが興奮する前に、はい、私は知っている、これは様々な基準の様々な声明をtrangresses。これは、頑固なバグを追跡するための完全に一時的な戦術として意図されています。throw、catch、sigaction macosx

Macでは、少なくとも動作しません。 sigaction関数のC++スローがterminateを呼び出します。

私はこの質問を投稿して、誰かがこれをうまく調整する方法を知っているかどうか尋ねます。

#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

Java例外にSIGSEGVを翻訳するのsetjmp/longjmpのを使用する、JNAのネイティブのビットを見てみましょう。

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

ああ、こんにちは、私は15年前にロングジャムでこれを書いていました。それでも最適な解決策はありますか?ところで、この質問のコードはLinuxで動作します。 – bmargulies

+0

FWIWでは、JNAの実装はさまざまなプラットフォームで動作しますが、スレッドセーフではありません(コンテキストの保存には静的変数を使用し、スレッドセーフな動作ではスレッドローカルにする必要があります)。 OSXの動作は、例外コンテキストがシグナルハンドラ内で有効ではないことを示しているようです。そのため、_terminate()が呼び出されるのです。 – technomage

関連する問題