95

私はプロジェクトを新しい Android Native Development Kit (つまり JNI) に移行しています。SIGSEGV が発生した場合 (おそらく SIGILL、SIGABRT、SIGFPE) をキャッチして、適切なクラッシュ レポート ダイアログを表示したいと考えています。 (またはその前に)現在何が起こっているか:プロセスの突然の突然の終了と、おそらくOSによる再起動の試み。(編集: JVM/Dalvik VM はシグナルをキャッチし、スタック トレースやその他の有用な情報をログに記録します。その情報を実際にメールで送信するオプションをユーザーに提供したいだけです。)

状況: 私が書いていない大量の C コードが、このアプリケーション (すべてのゲーム ロジック) のほとんどの作業を行っており、他の多くのプラットフォームで十分にテストされていますが、私の Android でポートは、ガベージをフィードし、ネイティブ コードでクラッシュを引き起こすため、現在 Android ログに表示されているクラッシュ ダンプ (ネイティブと Java の両方) が必要です (Android 以外の状況では stderr になると思います)。C コードと Java コードの両方を任意に変更することは自由ですが、コールバック (JNI に出入りする両方) の数は約 40 であり、明らかに、小さな差分にはボーナス ポイントがあります。

J2SE のシグナル チェーン ライブラリである libjsig.so について聞いたことがあります。そのようなシグナル ハンドラを Android に安全にインストールできれば、質問のキャッチ部分は解決しますが、Android/Dalvik 用のライブラリはありません。 .

4

4 に答える 4

83

編集: Jelly Bean 以降でREAD_LOGS、スタック トレースを取得できません。:-(

私は実際に、あまり風変わりなことをせずにシグナルハンドラーを動作させ、それを使用してコードをリリースしました。これはgithub で見ることができます(編集: 過去のリリースへのリンク; それ以来、クラッシュハンドラーを削除しました)。方法は次のとおりです。

  1. sigaction()シグナルをキャッチし、古いハンドラーを保存するために使用します。( android.c:570 )
  2. 時間が経つと、セグメンテーション違反が発生します。
  3. シグナル ハンドラーで、最後にもう一度 JNI を呼び出してから、古いハンドラーを呼び出します。( android.c:528 )
  4. その JNI 呼び出しで、有用なデバッグ情報をログに記録startActivity()し、独自のプロセスにある必要があるとフラグが付けられたアクティビティを呼び出します。( SGTPuzzles.java:962、AndroidManifest.xml:28 ) _ _
  5. Java から戻ってその古いハンドラーを呼び出すと、Android フレームワークが接続しdebuggerdて適切なネイティブ トレースをログに記録し、その後プロセスが終了します。( debugger.cdebuggerd.c )
  6. その間、クラッシュ処理アクティビティが開始されます。実際には、手順 5 が完了するまで待機できるように、PID を渡す必要があります。私はこれをしません。ここでは、ユーザーに謝罪し、ログを送信できるかどうか尋ねます。その場合は、 の出力を収集し、受信者、件名、本文を入力して をlogcat -d -v threadtime起動します。ユーザーは [送信] を押す必要があります。ACTION_SEND( CrashHandler.javaSGTPuzzles.java :462 、strings.xml:41
  7. logcat失敗したり、数秒以上かかったりしないように注意してください。T-Mobile Pulse / Huawei U8220 という 1 つのデバイスに遭遇しました。このデバイスでは、logcat がすぐにT(トレースされた) 状態になり、ハングします。( CrashHandler.java:70strings.xml:51 )

Android 以外の状況では、これの一部が異なります。独自のネイティブ トレースを収集する必要があります。使用している libc の種類に応じて、この他の質問を参照してください。そのトレースのダンプ、別のクラッシュ ハンドラ プロセスの起動、およびプラットフォームに適した方法での電子メールの送信を処理する必要がありますが、一般的なアプローチは引き続き機能するはずです。

于 2009-11-24T12:49:12.870 に答える
6

FWIW、GoogleBreakpadはAndroidで正常に動作します。移植作業を行い、FirefoxMobileの一部として出荷しています。クライアント側でスタックトレースを提供しないため、少しセットアップが必要ですが、生のスタックメモリを送信し、サーバー側でスタックウォーキングを行います(したがって、アプリにデバッグシンボルを同梱する必要はありません) )。

于 2011-11-08T20:17:39.087 に答える
5

私の限られた経験 (Android 以外) では、通常、JNI コードの SIGSEGV は、制御が Java コードに戻る前に JVM をクラッシュさせます。SIGSEGVをキャッチできるSun以外のJVMについて聞いたことを漠然と思い出しますが、AFAICRでそれができるとは期待できません。

プロセスの進行中の動作は公式に定義されていないため、SIGSEGV (または SIGFPE または SIGILL) ハンドラーの後にできることはほとんどありませんが、C でそれらをキャッチすることを試みることができます (sigaction(2) を参照)。

于 2009-07-05T01:55:16.597 に答える