debuggerd now notifies the Activity Manager about native crashes
The Activity Manager sets up a permission-guarded domain socket, which
debuggerd connects to when a crash happens. If this is successful,
the daemon then mirrors the logged crash report to that socket, then
closes it.
Bug 8322568
Change-Id: Ife0c772a628ef82e8457094e511ce1edbfe57460
diff --git a/debuggerd/utility.c b/debuggerd/utility.c
index aabaf74..de9200a 100644
--- a/debuggerd/utility.c
+++ b/debuggerd/utility.c
@@ -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);
}