Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ee72b0b authored by Christopher Tate's avatar Christopher Tate Committed by Android Git Automerger
Browse files

am a72f0ff0: am ded2e5ac: debuggerd now notifies the Activity Manager about native crashes

* commit 'a72f0ff0':
  debuggerd now notifies the Activity Manager about native crashes
parents ca203fc2 a72f0ff0
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -112,10 +112,11 @@ static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool a
    }
}

void dump_backtrace(int fd, pid_t pid, pid_t tid, bool* detach_failed,
void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed,
        int* total_sleep_time_usec) {
    log_t log;
    log.tfd = fd;
    log.amfd = amfd;
    log.quiet = true;

    ptrace_context_t* context = load_ptrace_context(tid);
+1 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@

/* Dumps a backtrace using a format similar to what Dalvik uses so that the result
 * can be intermixed in a bug report. */
void dump_backtrace(int fd, pid_t pid, pid_t tid, bool* detach_failed,
void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed,
        int* total_sleep_time_usec);

#endif // _DEBUGGERD_BACKTRACE_H
+2 −1
Original line number Diff line number Diff line
@@ -314,7 +314,8 @@ static void handle_request(int fd) {
                                    &total_sleep_time_usec);
                        } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) {
                            XLOG("stopped -- dumping to fd\n");
                            dump_backtrace(fd, request.pid, request.tid, &detach_failed,
                            dump_backtrace(fd, -1,
                                    request.pid, request.tid, &detach_failed,
                                    &total_sleep_time_usec);
                        } else {
                            XLOG("stopped -- continuing\n");
+59 −0
Original line number Diff line number Diff line
@@ -35,6 +35,9 @@
#include <corkscrew/demangle.h>
#include <corkscrew/backtrace.h>

#include <sys/socket.h>
#include <linux/un.h>

#include <selinux/android.h>

#include "machine.h"
@@ -47,6 +50,9 @@
#define MAX_TOMBSTONES  10
#define TOMBSTONE_DIR   "/data/tombstones"

/* Must match the path defined in NativeCrashListener.java */
#define NCRASH_SOCKET_PATH "/data/system/ndebugsocket"

#define typecheck(x,y) {    \
    typeof(x) __dummy1;     \
    typeof(y) __dummy2;     \
@@ -627,6 +633,18 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal,
    property_get("ro.debuggable", value, "0");
    bool want_logs = (value[0] == '1');

    if (log->amfd >= 0) {
        /*
         * Activity Manager protocol: binary 32-bit network-byte-order ints for the
         * pid and signal number, followed by the raw text of the dump, culminating
         * in a zero byte that marks end-of-data.
         */
        uint32_t datum = htonl(pid);
        TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
        datum = htonl(signal);
        TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
    }

    _LOG(log, false,
            "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
    dump_build_info(log);
@@ -653,6 +671,16 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal,
    if (want_logs) {
        dump_logs(log, pid, false);
    }

    /* send EOD to the Activity Manager, then wait for its ack to avoid racing ahead
     * and killing the target out from under it */
    if (log->amfd >= 0) {
        uint8_t eodMarker = 0;
        TEMP_FAILURE_RETRY( write(log->amfd, &eodMarker, 1) );
        /* 3 sec timeout reading the ack; we're fine if that happens */
        TEMP_FAILURE_RETRY( read(log->amfd, &eodMarker, 1) );
    }

    return detach_failed;
}

@@ -712,6 +740,35 @@ static char* find_and_open_tombstone(int* fd)
    return strdup(path);
}

static int activity_manager_connect() {
    int amfd = socket(PF_UNIX, SOCK_STREAM, 0);
    if (amfd >= 0) {
        struct sockaddr_un address;
        int err;

        memset(&address, 0, sizeof(address));
        address.sun_family = AF_UNIX;
        strncpy(address.sun_path, NCRASH_SOCKET_PATH, sizeof(address.sun_path));
        err = TEMP_FAILURE_RETRY( connect(amfd, (struct sockaddr*) &address, sizeof(address)) );
        if (!err) {
            struct timeval tv;
            memset(&tv, 0, sizeof(tv));
            tv.tv_sec = 1;  // tight leash
            err = setsockopt(amfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
            if (!err) {
                tv.tv_sec = 3;  // 3 seconds on handshake read
                err = setsockopt(amfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
            }
        }
        if (err) {
            close(amfd);
            amfd = -1;
        }
    }

    return amfd;
}

char* engrave_tombstone(pid_t pid, pid_t tid, int signal,
        bool dump_sibling_threads, bool quiet, bool* detach_failed,
        int* total_sleep_time_usec) {
@@ -732,10 +789,12 @@ char* engrave_tombstone(pid_t pid, pid_t tid, int signal,

    log_t log;
    log.tfd = fd;
    log.amfd = activity_manager_connect();
    log.quiet = quiet;
    *detach_failed = dump_crash(&log, pid, tid, signal, dump_sibling_threads,
            total_sleep_time_usec);

    close(log.amfd);
    close(fd);
    return path;
}
+39 −3
Original line number Diff line number Diff line
@@ -25,27 +25,63 @@
#include <cutils/logd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <assert.h>

#include "utility.h"

const int sleep_time_usec = 50000;         /* 0.05 seconds */
const int max_total_sleep_usec = 10000000; /* 10 seconds */

static int write_to_am(int fd, const char* buf, int len) {
    int to_write = len;
    while (to_write > 0) {
        int written = TEMP_FAILURE_RETRY( write(fd, buf + len - to_write, to_write) );
        if (written < 0) {
            /* hard failure */
            return -1;
        }
        to_write -= written;
    }
    return len;
}

void _LOG(log_t* log, bool in_tombstone_only, const char *fmt, ...) {
    char buf[512];
    bool want_tfd_write;
    bool want_log_write;
    bool want_amfd_write;
    int len;

    va_list ap;
    va_start(ap, fmt);

    if (log && log->tfd >= 0) {
        int len;
    // where is the information going to go?
    want_tfd_write = log && log->tfd >= 0;      // write to the tombstone fd?
    want_log_write = !in_tombstone_only && (!log || !log->quiet);
    want_amfd_write = log && log->amfd >= 0;    // only used when want_log_write is true

    // if we're going to need the literal string, generate it once here
    if (want_tfd_write || want_amfd_write) {
        vsnprintf(buf, sizeof(buf), fmt, ap);
        len = strlen(buf);
    }

    if (want_tfd_write) {
        write(log->tfd, buf, len);
    }

    if (!in_tombstone_only && (!log || !log->quiet)) {
    if (want_log_write) {
        // whatever goes to logcat also goes to the Activity Manager
        __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap);
        if (want_amfd_write && len > 0) {
            int written = write_to_am(log->amfd, buf, len);
            if (written <= 0) {
                // timeout or other failure on write; stop informing the activity manager
                LOG("AM write failure, giving up\n");
                log->amfd = -1;
            }
        }
    }
    va_end(ap);
}
Loading