My Android app (Java+NDK) reports a number of crashes (signals) caused by 0xdeadd00d. It's common knowledge that it's a shorthand for Dalvik VM abort. None of those happen inside my JNI calls, but the signal processing takes place in the native world. But the things that the native crash reporting normally reports (registers, stack) are of no use for debugging those.
Is there a way to get to the Java call stack from the native signal handler? Or to dump a portion of recent logcat activity?
Solution: introduce a special condition for deadd00d in the signal handler. Read the last 1024 bytes of logcat, jam it into the crash log.
I'm getting some decent diagnostics this way.
//n is the length of the file tail to read
//Returns # of byte read
size_t ReadLogcat(char *Buf, size_t n)
{
char s[sizeof(s_DataPath) + 30];
//s_DataPath contains the result of Context.getDir("Data")
strcpy(s, "logcat -d -f ");
char *fn = s + strlen(s);
strcat(s, s_DataPath);
strcat(s, "/logcat"); //Temp file for the logcat
size_t r = 0;
system(s); //Dump the snapshot of the logcat into the file called logcat
FILE *f = fopen(fn, "r");
if(f)
{
fseek(f, -n, SEEK_END); //We need the end of the file
r = fread(Buf, 1, n, f);
fclose(f);
}
unlink(fn); //Don't need the logcat file anymore
return r;
}
static void DumpLogcat(FILE *f)
{
char Buf[1024];
size_t r;
if(r = ReadLogcat(Buf, sizeof(Buf)))
{
fputs("\nLogcat:\n", f);
fwrite(Buf, 1, r, f);
}
}
void OnSignal(int signal, siginfo_t *si, void *p)
{
FILE *f = OpenCrashLog(); //opens a file in the data dir; details are irrelevant
//Lots of data dumping here... Version, stack, registers, etc.
//...
if((unsigned)si->si_addr == 0xdeadd00d) //Try and dump some Logcat
DumpLogcat(f);
}