Przenoszę projekt do nowego zestawu Android Native Development Kit (tj. JNI) i chciałbym złapać SIGSEGV, gdyby to się stało (prawdopodobnie również SIGILL, SIGABRT, SIGFPE), aby przedstawić ładne okno dialogowe raportowania awarii, zamiast (lub wcześniej) co się obecnie dzieje: natychmiastowa bezceremonialna śmierć procesu i prawdopodobnie próba ponownego uruchomienia go przez system operacyjny. ( Edycja: maszyna wirtualna JVM / Dalvik przechwytuje sygnał i rejestruje ślad stosu i inne przydatne informacje; chcę tylko zaoferować użytkownikowi opcję wysłania tych informacji e-mailem).
Sytuacja jest taka: duża część kodu C, którego nie napisałem, wykonuje większość pracy w tej aplikacji (cała logika gry) i chociaż jest dobrze przetestowany na wielu innych platformach, jest całkowicie możliwe, że ja w moim Androidzie port, prześle go do śmieci i spowoduje awarię w kodzie natywnym, więc chcę, aby zrzuty awaryjne (zarówno natywne, jak i Java), które są obecnie wyświetlane w dzienniku Androida (myślę, że byłby to stderr w sytuacji innej niż Android). Mogę dowolnie modyfikować zarówno kod C, jak i Java, chociaż wywołania zwrotne (zarówno wchodzące, jak i wychodzące z JNI) mają około 40 i oczywiście punkty bonusowe za małe różnice.
Słyszałem o bibliotece łańcuchów sygnałów w J2SE, libjsig.so, i gdybym mógł bezpiecznie zainstalować taką obsługę sygnału w systemie Android, rozwiązałoby to chwytliwą część mojego pytania, ale nie widzę takiej biblioteki dla Androida / Dalvik .
Odpowiedzi:
Edycja: począwszy od Jelly Bean nie można uzyskać śladu stosu, ponieważ
READ_LOGS
odszedł . :-(Właściwie mam moduł obsługi sygnału działający bez robienia niczego zbyt egzotycznego i wydałem kod, używając go, co można zobaczyć na github (edycja: link do wydania historycznego; od tego czasu usunąłem obsługę awarii). Oto jak:
sigaction()
do przechwytywania sygnałów i przechowywania starych uchwytów. ( android.c: 570 )startActivity()
działanie, które jest oznaczone jako musi znajdować się we własnym procesie. ( SGTPuzzles.java:962 , AndroidManifest.xml: 28 )debuggerd
aby zarejestrować ładny natywny ślad, a następnie proces umrze. ( debugger.c , debuggerd.c )logcat -d -v threadtime
i uruchom wiadomośćACTION_SEND
z odbiorcą, tematem i treścią wypełnioną. Użytkownik będzie musiał nacisnąć Wyślij. ( CrashHandler.java , SGTPuzzles.java:462 , strings.xml: 41logcat
awarie lub zajęcie więcej niż kilka sekund. Spotkałem jedno urządzenie, T-Mobile Pulse / Huawei U8220, w którym logcat natychmiast przechodzi w stanT
(śledzony) i zawiesza się. ( CrashHandler.java:70 , strings.xml : 51 )W sytuacji bez Androida niektóre z nich byłyby inne. Musiałbyś zebrać swój własny natywny ślad, zobacz to inne pytanie , w zależności od rodzaju posiadanej biblioteki libc. Musiałbyś poradzić sobie z zrzuceniem tego śladu, uruchomieniem oddzielnego procesu obsługi awarii i wysłaniem wiadomości e-mail w odpowiedni sposób dla Twojej platformy, ale wyobrażam sobie, że ogólne podejście powinno nadal działać.
źródło
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
debuggerd
wyników?Jestem trochę późno, ale miałem dokładnie taką samą potrzebę, i ja stworzyliśmy małą bibliotekę, aby go rozwiązać, łapiąc typowych awarii (
SEGV
,SIBGUS
itp) wewnątrz kodu JNI , i zastąpić je regularniejava.lang.Error
wyjątkami . Dodatkowo, jeśli klient działa na systemie Android> =4.1.1
, ślad stosu osadza rozwiązany ślad wstecznej awarii (pseudo-ślad zawierający pełny natywny ślad stosu). Nie odzyskasz sprawności po błędnych awariach (np. Jeśli uszkodzisz alokator), ale przynajmniej powinno to pozwolić ci na odzyskanie większości z nich. (prosimy o zgłaszanie sukcesów i porażek, kod jest nowy)Więcej informacji na https://github.com/xroche/coffeecatch (kod to licencja BSD 2-Clauses )
źródło
FWIW, Google Breakpad działa dobrze na Androidzie. Wykonałem prace związane z przenoszeniem i wysyłamy to jako część Firefoksa Mobile. Wymaga niewielkiej konfiguracji, ponieważ nie daje śladów stosu po stronie klienta, ale wysyła nieprzetworzoną pamięć stosu i wykonuje spacer po stosie po stronie serwera (więc nie musisz wysyłać symboli debugowania z aplikacją ).
źródło
Z mojego ograniczonego doświadczenia (inne niż Android), SIGSEGV w kodzie JNI generalnie spowoduje awarię JVM, zanim kontrola zostanie zwrócona do kodu Java. Mglisto przypominam sobie, że słyszałem o jakiejś innej maszynie JVM innej niż Sun, która pozwala złapać SIGSEGV, ale AFAICR nie możesz oczekiwać, że będziesz w stanie to zrobić.
Możesz spróbować złapać je w C (patrz sigaction (2)), chociaż możesz zrobić bardzo niewiele po obsłudze SIGSEGV (lub SIGFPE lub SIGILL), ponieważ bieżące zachowanie procesu jest oficjalnie nieokreślone.
źródło
_Unwind_Backtrace
z odunwind.h
.