summaryrefslogtreecommitdiffstats
path: root/runtime/runtime_android.cc
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2014-02-26 17:16:38 -0800
committerMathieu Chartier <mathieuc@google.com>2014-02-28 17:02:17 -0800
commit15d3402bbf8265eb1165694da2e4117eb128f3bc (patch)
treeeea2dae3c338d3070f63e086fa2a3669a9204873 /runtime/runtime_android.cc
parentba8fdcc10193cdfa825c973d740b7ebf6dec2d89 (diff)
downloadart-15d3402bbf8265eb1165694da2e4117eb128f3bc.tar.gz
art-15d3402bbf8265eb1165694da2e4117eb128f3bc.tar.bz2
art-15d3402bbf8265eb1165694da2e4117eb128f3bc.zip
Add custom SIGSEGV handler to help find heap corruption.
The new signal handler prints heap diagnostics when you get a SIGSEGV. Added a fault message member in runtime which is modifiable by Runtime::SetFaultMessage. When you get a SIGSEGV it will print out whatever is stored in this string as well as the normal information. This is useful for debugging heap corruption since it lets you see which threads were in which methods when the last GC occured. Added some smarter object dumping logic when the faulting address is in the heap. Bug: 12934910 Change-Id: Ia72be2c39f70ad711cbd746d66fad2b617d5d29f
Diffstat (limited to 'runtime/runtime_android.cc')
-rw-r--r--runtime/runtime_android.cc50
1 files changed, 48 insertions, 2 deletions
diff --git a/runtime/runtime_android.cc b/runtime/runtime_android.cc
index 2013294dfb..14e557450b 100644
--- a/runtime/runtime_android.cc
+++ b/runtime/runtime_android.cc
@@ -14,12 +14,58 @@
* limitations under the License.
*/
-#include "runtime.h"
+#include <signal.h>
+#include <string.h>
+#include <sys/utsname.h>
+#include <inttypes.h>
+
+#include "base/logging.h"
+#include "base/mutex.h"
+#include "base/stringprintf.h"
+#include "thread-inl.h"
+#include "utils.h"
namespace art {
+struct sigaction old_action;
+void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context) {
+ static bool handlingUnexpectedSignal = false;
+ if (handlingUnexpectedSignal) {
+ LogMessageData data(__FILE__, __LINE__, INTERNAL_FATAL, -1);
+ LogMessage::LogLine(data, "HandleUnexpectedSignal reentered\n");
+ _exit(1);
+ }
+ handlingUnexpectedSignal = true;
+ gAborting++; // set before taking any locks
+ MutexLock mu(Thread::Current(), *Locks::unexpected_signal_lock_);
+
+ Runtime* runtime = Runtime::Current();
+ if (runtime != nullptr) {
+ // Print this out first in case DumpObject faults.
+ LOG(INTERNAL_FATAL) << "Fault message: " << runtime->GetFaultMessage();
+ gc::Heap* heap = runtime->GetHeap();
+ if (heap != nullptr && info != nullptr) {
+ LOG(INTERNAL_FATAL) << "Dump heap object at fault address: ";
+ heap->DumpObject(LOG(INTERNAL_FATAL), reinterpret_cast<mirror::Object*>(info->si_addr));
+ }
+ }
+ // Run the old signal handler.
+ old_action.sa_sigaction(signal_number, info, raw_context);
+}
+
void Runtime::InitPlatformSignalHandlers() {
- // On a device, debuggerd will give us a stack trace. Nothing to do here.
+ // On the host, we don't have debuggerd to dump a stack for us when something unexpected happens.
+ struct sigaction action;
+ memset(&action, 0, sizeof(action));
+ sigemptyset(&action.sa_mask);
+ action.sa_sigaction = HandleUnexpectedSignal;
+ // Use the three-argument sa_sigaction handler.
+ action.sa_flags |= SA_SIGINFO;
+ // Use the alternate signal stack so we can catch stack overflows.
+ action.sa_flags |= SA_ONSTACK;
+ int rc = 0;
+ rc += sigaction(SIGSEGV, &action, &old_action);
+ CHECK_EQ(rc, 0);
}
} // namespace art