Android app restarts automatically after a crash-ThrowExceptions

Exception or error:

My app is partly written in native app using C/C++. The problem is that whenever C/C++ part crashes for some reason the app dies and then restarts automatically. This causes all kinds of messy problems

Now of course, it should not crash in the native part and I’m trying to weed out all reasons why it would happen. However, if it does happen I’d like to:

  1. Quit gracefully
  2. If it does die, at least not try to restart automatically.

I’m curious as to why this behaviour happens. After some search I tried putting the following line in the main activity element of the AndroidManifest.xml:

android:finishOnTaskLaunch="true"

but the automatic restore still happens.

Anyone knows why this is happening and how to change it?

UPDATE:
I think a more fundamental question is,
Is there something similar to a callback if there is a native crash?

One of the answers suggested ‘handling crash signals’. I’d be grateful for any links on how it can be done at an application or module level.

As it stands currently, if there is a crash the app just disappears, there’s nothing in logcat, so no debugging is possible.

How to solve:

Try to handle crash signals (SIGSEGV etc.) and send kill to yourself in signal handler. This trick helps me.

Example:

#include <signal.h>
#include <unistd.h>


static void signal_handler(int signal, siginfo_t *info, void *reserved)
{
  kill(getpid(),SIGKILL);
}

extern "C" jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
{
  struct sigaction handler;
  memset(&handler, 0, sizeof(handler));
  handler.sa_sigaction = signal_handler;
  handler.sa_flags = SA_SIGINFO;
  sigaction(SIGILL, &handler, NULL);
  sigaction(SIGABRT, &handler, NULL);
  sigaction(SIGBUS, &handler, NULL);
  sigaction(SIGFPE, &handler, NULL);
  sigaction(SIGSEGV, &handler, NULL);
  sigaction(SIGSTKFLT, &handler, NULL);
  return(JNI_VERSION_1_6);
}

UPDATE2

if you want to see crashlog in android logcat you should use this signal handler

static void signal_handler(int signal, siginfo_t *info, void *reserved)
{
 struct sockaddr_un addr;
 size_t namelen;
 socklen_t alen;
 int s, err;
 char name[] = "android:debuggerd";
 namelen  = strlen(name);

 // Test with length +1 for the *initial* '\0'.
 if ((namelen + 1) > sizeof(addr.sun_path)) {
    errno = EINVAL;
    return;
 }

 /* This is used for abstract socket namespace, we need
  * an initial '\0' at the start of the Unix socket path.
  *
  * Note: The path in this case is *not* supposed to be
  * '\0'-terminated. ("man 7 unix" for the gory details.)
  */
 memset (&addr, 0, sizeof addr);
 addr.sun_family = AF_LOCAL;
 addr.sun_path[0] = 0;
 memcpy(addr.sun_path + 1, name, namelen);

 alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;

 s = socket(AF_LOCAL, SOCK_STREAM, 0);
 if(s < 0) return;

 RETRY_ON_EINTR(err,connect(s, (struct sockaddr *) &addr, alen));
 if (err < 0) {
    close(s);
    s = -1;
 }

 pid_t tid = gettid();
 if(s>=0)
 {
   /* debugger knows our pid from the credentials on the
    * local socket but we need to tell it our tid.  It
    * is paranoid and will verify that we are giving a tid
    * that's actually in our process
    */
    int  ret;

    RETRY_ON_EINTR(ret, write(s, &tid, sizeof(unsigned)));
    if (ret == sizeof(unsigned)) {
        /* if the write failed, there is no point to read on
         * the file descriptor. */
        RETRY_ON_EINTR(ret, read(s, &tid, 1));
        //notify_gdb_of_libraries();
    }
    close(s);
 }

 wait(NULL);
 kill(getpid(),SIGKILL);
}

I took it from android source (can’t insert link because android.git.kernel.org is down), but I am not sure that it will work in future Android releases

###

By default your application should not be automatically restarting. Generally one would have to register for this kind of thing, e.g. via the AlarmManager/keep alives.

Do you have a service as part of your application?

Leave a Reply

Your email address will not be published. Required fields are marked *