Merge "Catch SIGBUS in HeapWalker" am: b566e3cb2f am: 9926972bff

am: 549346f9ee

Change-Id: I77eecda271e3dffcd1dd902c75fff4d559a9c9cc
This commit is contained in:
Colin Cross 2019-03-21 12:28:24 -07:00 committed by android-build-merger
commit ea4eaba147
3 changed files with 33 additions and 11 deletions

View file

@ -207,6 +207,6 @@ void HeapWalker::HandleSegFault(ScopedSignalHandler& handler, int signal, siginf
}
}
ScopedSignalHandler::SignalFn ScopedSignalHandler::handler_;
Allocator<ScopedSignalHandler::SignalFnMap>::unique_ptr ScopedSignalHandler::handler_map_;
} // namespace android

View file

@ -52,7 +52,8 @@ class HeapWalker {
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 @@ class HeapWalker {
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 @@ class HeapWalker {
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_;

View file

@ -24,6 +24,7 @@
#include "android-base/macros.h"
#include "Allocator.h"
#include "log.h"
namespace android {
@ -32,17 +33,29 @@ class ScopedSignalHandler {
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 @@ class ScopedSignalHandler {
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