Log line-at-a-time to work around Android logging lossage.

Also deduplicate the two copies of gettid, and switch image_test over
to using SignalCatcher's SIGQUIT dumping rather than rolling its own
subset.

Change-Id: I8b70aaa3a3b9258c8258728c6a66e5dc4fa6399e
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 53f7667..72d42d1 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -76,6 +76,7 @@
 	src/java_util_concurrent_atomic_AtomicLong.cc \
 	src/jni_compiler.cc \
 	src/jni_internal.cc \
+	src/logging.cc \
 	src/mark_stack.cc \
 	src/mark_sweep.cc \
 	src/memory_region.cc \
diff --git a/src/common_test.h b/src/common_test.h
index 4ed61f2..7916640 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -63,19 +63,6 @@
 
 class CommonTest : public testing::Test {
  public:
-  static void LogMaps() {
-    const char* maps_file = "/proc/self/maps";
-    std::string contents;
-    CHECK(ReadFileToString(maps_file, &contents));
-    // logcat can't handle it all at once
-    std::vector<std::string> lines;
-    Split(contents, '\n', lines);
-    LOG(INFO) << maps_file << ":";
-    for (size_t i = 0; i < lines.size(); i++) {
-      LOG(INFO) << "    " << lines[i];
-    }
-  }
-
   static void MakeExecutable(const ByteArray* byte_array) {
     uintptr_t data = reinterpret_cast<uintptr_t>(byte_array->GetData());
     uintptr_t base = RoundDown(data, kPageSize);
diff --git a/src/image_test.cc b/src/image_test.cc
index d54c3ce..db09021 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -7,6 +7,7 @@
 #include "file.h"
 #include "image.h"
 #include "image_writer.h"
+#include "signal_catcher.h"
 #include "space.h"
 #include "utils.h"
 
@@ -72,9 +73,9 @@
   ASSERT_TRUE(boot_space != NULL);
 
   // enable to display maps to debug boot_base and boot_limit checking problems below
-  if (false) {
-    // TODO: switch to sending kill -3 to self
-    LogMaps();
+  // TODO: why does this dump show two attached threads?
+  if (true) {
+    SignalCatcher::HandleSigQuit();
   }
 
   byte* boot_base = boot_space->GetBase();
diff --git a/src/logging.h b/src/logging.h
index bf6d179..43596b5 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -1,15 +1,18 @@
-// Copyright 2010 Google
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #ifndef ART_SRC_LOGGING_H_
 #define ART_SRC_LOGGING_H_
@@ -123,10 +126,11 @@
   std::ostream& stream();
 
  private:
+  void LogLine(const char*);
+
   std::stringstream buffer_;
-  std::ios_base::fmtflags stream_state_;
   const char* file_;
-  int line_;
+  int line_number_;
   LogSeverity severity_;
   int errno_;
 
diff --git a/src/logging_android.cc b/src/logging_android.cc
index 8acb6ef..0d64c60 100644
--- a/src/logging_android.cc
+++ b/src/logging_android.cc
@@ -1,4 +1,18 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include "logging.h"
 
@@ -6,28 +20,17 @@
 #include <unistd.h>
 
 #include "cutils/log.h"
-#include "runtime.h"
 
 static const int kLogSeverityToAndroidLogPriority[] = {
   ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL
 };
 
 LogMessage::LogMessage(const char* file, int line, LogSeverity severity, int error)
-: file_(file), line_(line), severity_(severity), errno_(error)
+: file_(file), line_number_(line), severity_(severity), errno_(error)
 {
 }
 
-LogMessage::~LogMessage() {
-  if (errno_ != -1) {
-    stream() << ": " << strerror(errno_);
-  }
+void LogMessage::LogLine(const char* line) {
   int priority = kLogSeverityToAndroidLogPriority[severity_];
-  LOG_PRI(priority, LOG_TAG, "%s", buffer_.str().c_str());
-  if (severity_ == FATAL) {
-    art::Runtime::Abort(file_, line_);
-  }
-}
-
-std::ostream& LogMessage::stream() {
-  return buffer_;
+  LOG_PRI(priority, LOG_TAG, "%s", line);
 }
diff --git a/src/logging_linux.cc b/src/logging_linux.cc
index 96e7fbf..fd12b98 100644
--- a/src/logging_linux.cc
+++ b/src/logging_linux.cc
@@ -1,4 +1,18 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include <sys/types.h>
 #include <unistd.h>
@@ -8,40 +22,17 @@
 #include <iostream>
 
 #include "logging.h"
-#include "runtime.h"
 #include "stringprintf.h"
-
-// glibc doesn't expose gettid(2).
-#define __KERNEL__
-# include <linux/unistd.h>
-#ifdef _syscall0
-_syscall0(pid_t,gettid)
-#else
-pid_t gettid() { return syscall(__NR_gettid);}
-#endif
-#undef __KERNEL__
+#include "utils.h"
 
 LogMessage::LogMessage(const char* file, int line, LogSeverity severity, int error)
-: line_(line), severity_(severity), errno_(error)
+: line_number_(line), severity_(severity), errno_(error)
 {
-  stream_state_ = stream().flags();
   const char* last_slash = strrchr(file, '/');
   file_ = (last_slash == NULL) ? file : last_slash + 1;
-  stream() << StringPrintf("%c %5d %5d %s:%d] ",
-      "IWEF"[severity], getpid(), gettid(), file_, line);
 }
 
-LogMessage::~LogMessage() {
-  if (errno_ != -1) {
-    stream() << ": " << strerror(errno_);
-  }
-  stream() << std::endl;
-  stream().flags(stream_state_);
-  if (severity_ == FATAL) {
-    art::Runtime::Abort(file_, line_);
-  }
-}
-
-std::ostream& LogMessage::stream() {
-  return std::cerr;
+void LogMessage::LogLine(const char* line) {
+  std::cerr << "IWEF"[severity_] << ' ' << StringPrintf("%5d %5d", getpid(), ::art::GetTid()) << ' '
+            << file_ << ':' << line_number_ << "] " << line << std::endl;
 }
diff --git a/src/runtime.cc b/src/runtime.cc
index bb3ead7..2891e56 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -399,6 +399,7 @@
   //    gDvm.numDeclaredStaticFields,
   //    gDvm.pBootLoaderAlloc->curOffset);
   // LOGI("GC precise methods: %d", dvmPointerSetGetCount(gDvm.preciseMethods));
+  os << "\n";
 }
 
 void Runtime::BlockSignals() {
diff --git a/src/signal_catcher.h b/src/signal_catcher.h
index 1c08542..a31b9f1 100644
--- a/src/signal_catcher.h
+++ b/src/signal_catcher.h
@@ -34,9 +34,10 @@
   SignalCatcher();
   ~SignalCatcher();
 
+  static void HandleSigQuit();
+
  private:
   static void* Run(void* arg);
-  static void HandleSigQuit();
   static void HandleSigUsr1();
 
   static bool halt_;
diff --git a/src/thread.cc b/src/thread.cc
index 5da02ae..97cc8ea 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -20,18 +20,6 @@
 
 namespace art {
 
-/* desktop Linux needs a little help with gettid() */
-#if !defined(HAVE_ANDROID_OS)
-#define __KERNEL__
-# include <linux/unistd.h>
-#ifdef _syscall0
-_syscall0(pid_t, gettid)
-#else
-pid_t gettid() { return syscall(__NR_gettid);}
-#endif
-#undef __KERNEL__
-#endif
-
 pthread_key_t Thread::pthread_key_self_;
 
 // Temporary debugging hook for compiler.
@@ -267,7 +255,7 @@
   thread->InitCpu();
 
   thread->handle_ = pthread_self();
-  thread->tid_ = gettid();
+  thread->tid_ = ::art::GetTid();
 
   thread->state_ = kRunnable;
 
@@ -798,6 +786,7 @@
   for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
     (*it)->Dump(os);
   }
+  os << "\n";
 }
 
 void ThreadList::Register(Thread* thread) {
diff --git a/src/utils.cc b/src/utils.cc
index 3be3fa6..90dd842 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -1,11 +1,16 @@
 // Copyright 2011 Google Inc. All Rights Reserved.
 // Author: enh@google.com (Elliott Hughes)
 
+#include "utils.h"
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
 #include "UniquePtr.h"
 #include "file.h"
 #include "object.h"
 #include "os.h"
-#include "utils.h"
 
 namespace art {
 
@@ -209,3 +214,15 @@
 }
 
 }  // namespace art
+
+// Neither bionic nor glibc exposes gettid(2).
+#define __KERNEL__
+#include <linux/unistd.h>
+namespace art {
+#ifdef _syscall0
+_syscall0(pid_t, GetTid)
+#else
+pid_t GetTid() { return syscall(__NR_gettid); }
+#endif
+}  // namespace art
+#undef __KERNEL__
diff --git a/src/utils.h b/src/utils.h
index 4c2a7f9..69ca168 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -177,6 +177,9 @@
 // strings. Empty strings will be omitted.
 void Split(const std::string& s, char delim, std::vector<std::string>& result);
 
+// Returns the calling thread's tid. (The C libraries don't expose this.)
+pid_t GetTid();
+
 }  // namespace art
 
 #endif  // ART_SRC_UTILS_H_