Search code examples
androidandroid-ndklogcat

How do I find relevant deadd00d circumstances from customer devices?


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

  • 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);
    }