Improve liblog's fatal logging.

This makes LOG_ALWAYS_FATAL and LOG_ALWAYS_FATAL_IF as good as regular
assert(3).

Change-Id: I0666684d30cae7baf23c64b33d35c1e43f81acf0
diff --git a/debuggerd/crasher.c b/debuggerd/crasher.c
index 5a2bc3c..9946faa 100644
--- a/debuggerd/crasher.c
+++ b/debuggerd/crasher.c
@@ -1,20 +1,17 @@
-
-//#include <cutils/misc.h>
-
-#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sched.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sched.h>
-#include <errno.h>
-
-#include <signal.h>
 #include <sys/ptrace.h>
-#include <sys/wait.h>
 #include <sys/socket.h>
+#include <sys/wait.h>
+#include <unistd.h>
 
-#include <pthread.h>
-
+#include <cutils/log.h>
 #include <cutils/sockets.h>
 
 extern const char* __progname;
@@ -23,8 +20,8 @@
 void crashnostack(void);
 static int do_action(const char* arg);
 
-static void maybeabort() {
-    if(time(0) != 42) {
+static void maybe_abort() {
+    if (time(0) != 42) {
         abort();
     }
 }
@@ -119,20 +116,28 @@
 
     if (!strncmp(arg, "thread-", strlen("thread-"))) {
         return do_action_on_thread(arg + strlen("thread-"));
-    } else if (!strcmp(arg,"smash-stack")) {
+    } else if (!strcmp(arg, "smash-stack")) {
         return smash_stack(42);
-    } else if (!strcmp(arg,"stack-overflow")) {
+    } else if (!strcmp(arg, "stack-overflow")) {
         overflow_stack(NULL);
-    } else if (!strcmp(arg,"nostack")) {
+    } else if (!strcmp(arg, "nostack")) {
         crashnostack();
-    } else if (!strcmp(arg,"ctest")) {
+    } else if (!strcmp(arg, "ctest")) {
         return ctest();
-    } else if (!strcmp(arg,"exit")) {
+    } else if (!strcmp(arg, "exit")) {
         exit(1);
-    } else if (!strcmp(arg,"crash")) {
+    } else if (!strcmp(arg, "crash")) {
         return crash(42);
-    } else if (!strcmp(arg,"abort")) {
-        maybeabort();
+    } else if (!strcmp(arg, "abort")) {
+        maybe_abort();
+    } else if (!strcmp(arg, "assert")) {
+        __assert("some_file.c", 123, "false");
+    } else if (!strcmp(arg, "assert2")) {
+      __assert2("some_file.c", 123, "some_function", "false");
+    } else if (!strcmp(arg, "LOG_ALWAYS_FATAL")) {
+        LOG_ALWAYS_FATAL("hello %s", "world");
+    } else if (!strcmp(arg, "LOG_ALWAYS_FATAL_IF")) {
+        LOG_ALWAYS_FATAL_IF(true, "hello %s", "world");
     } else if (!strcmp(arg, "heap-usage")) {
         abuse_heap();
     }
@@ -148,6 +153,8 @@
     fprintf(stderr, "  exit            call exit(1)\n");
     fprintf(stderr, "  crash           cause a SIGSEGV\n");
     fprintf(stderr, "  abort           call abort()\n");
+    fprintf(stderr, "  assert          call assert() without a function\n");
+    fprintf(stderr, "  assert2         call assert() with a function\n");
     fprintf(stderr, "prefix any of the above with 'thread-' to not run\n");
     fprintf(stderr, "on the process' main thread.\n");
     return EXIT_SUCCESS;
diff --git a/include/android/log.h b/include/android/log.h
index 0ea4c29..f5b1900 100644
--- a/include/android/log.h
+++ b/include/android/log.h
@@ -110,11 +110,11 @@
                          const char *fmt, va_list ap);
 
 /*
- * Log an assertion failure and SIGTRAP the process to have a chance
- * to inspect it, if a debugger is attached. This uses the FATAL priority.
+ * Log an assertion failure and abort the process to have a chance
+ * to inspect it if a debugger is attached. This uses the FATAL priority.
  */
 void __android_log_assert(const char *cond, const char *tag,
-			  const char *fmt, ...)    
+                          const char *fmt, ...)
 #if defined(__GNUC__)
     __attribute__ ((noreturn))
     __attribute__ ((format(printf, 3, 4)))
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 94722d3..48531d5 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -407,9 +407,15 @@
             strcpy(buf, "Unspecified assertion failed");
     }
 
+#if __BIONIC__
+    // Ensure debuggerd gets to see what went wrong by keeping the C library in the loop.
+    extern __noreturn void __android_fatal(const char* tag, const char* format, ...) __printflike(2, 3);
+    __android_fatal(tag ? tag : "", "%s", buf);
+#else
     __android_log_write(ANDROID_LOG_FATAL, tag, buf);
-
     __builtin_trap(); /* trap so we have a chance to debug the situation */
+#endif
+    /* NOTREACHED */
 }
 
 int __android_log_bwrite(int32_t tag, const void *payload, size_t len)
diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c
index c29c28f..8c707ad 100644
--- a/liblog/logd_write_kern.c
+++ b/liblog/logd_write_kern.c
@@ -272,9 +272,15 @@
             strcpy(buf, "Unspecified assertion failed");
     }
 
+#if __BIONIC__
+    // Ensure debuggerd gets to see what went wrong by keeping the C library in the loop.
+    extern __noreturn void __android_fatal(const char* tag, const char* format, ...) __printflike(2, 3);
+    __android_fatal(tag ? tag : "", "%s", buf);
+#else
     __android_log_write(ANDROID_LOG_FATAL, tag, buf);
-
     __builtin_trap(); /* trap so we have a chance to debug the situation */
+#endif
+    /* NOTREACHED */
 }
 
 int __android_log_bwrite(int32_t tag, const void *payload, size_t len)