Catch SIGBUS in HeapWalker
SIGBUS shouldn't happen, since all of the regions being walked
were previously read out of /prod/pid/maps, but it seems to happen
rarely. Catch it so it can produce a better log message.
Bug: 128983715
Test: atest memunreachable_test
Change-Id: I82d3941a382a0451c0dda12f5eb849ad8d697bc9
diff --git a/libmemunreachable/HeapWalker.cpp b/libmemunreachable/HeapWalker.cpp
index e11f079..7cae048 100644
--- a/libmemunreachable/HeapWalker.cpp
+++ b/libmemunreachable/HeapWalker.cpp
@@ -207,6 +207,6 @@
}
}
-ScopedSignalHandler::SignalFn ScopedSignalHandler::handler_;
+Allocator<ScopedSignalHandler::SignalFnMap>::unique_ptr ScopedSignalHandler::handler_map_;
} // namespace android
diff --git a/libmemunreachable/HeapWalker.h b/libmemunreachable/HeapWalker.h
index 9e3db08..f00bcca 100644
--- a/libmemunreachable/HeapWalker.h
+++ b/libmemunreachable/HeapWalker.h
@@ -52,7 +52,8 @@
allocation_bytes_(0),
roots_(allocator),
root_vals_(allocator),
- segv_handler_(),
+ sigsegv_handler_(allocator),
+ sigbus_handler_(allocator),
walking_ptr_(0),
walking_range_{0, 0},
segv_logged_(false),
@@ -62,10 +63,14 @@
valid_mappings_range_.end = 0;
valid_mappings_range_.begin = ~valid_allocations_range_.end;
- segv_handler_.install(
+ sigsegv_handler_.install(
SIGSEGV, [=](ScopedSignalHandler& handler, int signal, siginfo_t* siginfo, void* uctx) {
this->HandleSegFault(handler, signal, siginfo, uctx);
});
+ sigbus_handler_.install(
+ SIGBUS, [=](ScopedSignalHandler& handler, int signal, siginfo_t* siginfo, void* uctx) {
+ this->HandleSegFault(handler, signal, siginfo, uctx);
+ });
}
~HeapWalker() {}
@@ -106,7 +111,8 @@
allocator::vector<Range> roots_;
allocator::vector<uintptr_t> root_vals_;
- ScopedSignalHandler segv_handler_;
+ ScopedSignalHandler sigsegv_handler_;
+ ScopedSignalHandler sigbus_handler_;
volatile uintptr_t walking_ptr_;
Range walking_range_;
bool segv_logged_;
diff --git a/libmemunreachable/ScopedSignalHandler.h b/libmemunreachable/ScopedSignalHandler.h
index 9e08a8e..ef4473f 100644
--- a/libmemunreachable/ScopedSignalHandler.h
+++ b/libmemunreachable/ScopedSignalHandler.h
@@ -24,6 +24,7 @@
#include "android-base/macros.h"
+#include "Allocator.h"
#include "log.h"
namespace android {
@@ -32,17 +33,29 @@
public:
using Fn = std::function<void(ScopedSignalHandler&, int, siginfo_t*, void*)>;
- explicit ScopedSignalHandler() : signal_(-1) {}
+ explicit ScopedSignalHandler(Allocator<ScopedSignalHandler> allocator) : signal_(-1) {
+ if (handler_map_ == nullptr) {
+ Allocator<SignalFnMap> map_allocator = allocator;
+ handler_map_ = map_allocator.make_unique(allocator);
+ }
+ }
~ScopedSignalHandler() { reset(); }
template <class F>
void install(int signal, F&& f) {
if (signal_ != -1) MEM_LOG_ALWAYS_FATAL("ScopedSignalHandler already installed");
- handler_ = SignalFn([=](int signal, siginfo_t* si, void* uctx) { f(*this, signal, si, uctx); });
+ if (handler_map_->find(signal) != handler_map_->end()) {
+ MEM_LOG_ALWAYS_FATAL("ScopedSignalHandler already installed for %d", signal);
+ }
+
+ (*handler_map_)[signal] =
+ SignalFn([=](int signal, siginfo_t* si, void* uctx) { f(*this, signal, si, uctx); });
struct sigaction act {};
- act.sa_sigaction = [](int signal, siginfo_t* si, void* uctx) { handler_(signal, si, uctx); };
+ act.sa_sigaction = [](int signal, siginfo_t* si, void* uctx) {
+ ((*handler_map_)[signal])(signal, si, uctx);
+ };
act.sa_flags = SA_SIGINFO;
int ret = sigaction(signal, &act, &old_act_);
@@ -59,19 +72,22 @@
if (ret < 0) {
MEM_ALOGE("failed to uninstall segfault handler");
}
- handler_ = SignalFn{};
+
+ handler_map_->erase(signal_);
+ if (handler_map_->empty()) {
+ handler_map_.reset();
+ }
signal_ = -1;
}
}
private:
using SignalFn = std::function<void(int, siginfo_t*, void*)>;
+ using SignalFnMap = allocator::unordered_map<int, SignalFn>;
DISALLOW_COPY_AND_ASSIGN(ScopedSignalHandler);
int signal_;
struct sigaction old_act_;
- // TODO(ccross): to support multiple ScopedSignalHandlers handler_ would need
- // to be a static map of signals to handlers, but allocated with Allocator.
- static SignalFn handler_;
+ static Allocator<SignalFnMap>::unique_ptr handler_map_;
};
} // namespace android