Merge "Catch SIGBUS in HeapWalker" am: b566e3cb2f
am: 9926972bff
Change-Id: Ia15f16850b100a32f7189ebef8819f09e465d90f
This commit is contained in:
commit
549346f9ee
3 changed files with 33 additions and 11 deletions
|
|
@ -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
|
} // namespace android
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,8 @@ class HeapWalker {
|
||||||
allocation_bytes_(0),
|
allocation_bytes_(0),
|
||||||
roots_(allocator),
|
roots_(allocator),
|
||||||
root_vals_(allocator),
|
root_vals_(allocator),
|
||||||
segv_handler_(),
|
sigsegv_handler_(allocator),
|
||||||
|
sigbus_handler_(allocator),
|
||||||
walking_ptr_(0),
|
walking_ptr_(0),
|
||||||
walking_range_{0, 0},
|
walking_range_{0, 0},
|
||||||
segv_logged_(false),
|
segv_logged_(false),
|
||||||
|
|
@ -62,10 +63,14 @@ class HeapWalker {
|
||||||
valid_mappings_range_.end = 0;
|
valid_mappings_range_.end = 0;
|
||||||
valid_mappings_range_.begin = ~valid_allocations_range_.end;
|
valid_mappings_range_.begin = ~valid_allocations_range_.end;
|
||||||
|
|
||||||
segv_handler_.install(
|
sigsegv_handler_.install(
|
||||||
SIGSEGV, [=](ScopedSignalHandler& handler, int signal, siginfo_t* siginfo, void* uctx) {
|
SIGSEGV, [=](ScopedSignalHandler& handler, int signal, siginfo_t* siginfo, void* uctx) {
|
||||||
this->HandleSegFault(handler, signal, siginfo, 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() {}
|
~HeapWalker() {}
|
||||||
|
|
@ -106,7 +111,8 @@ class HeapWalker {
|
||||||
allocator::vector<Range> roots_;
|
allocator::vector<Range> roots_;
|
||||||
allocator::vector<uintptr_t> root_vals_;
|
allocator::vector<uintptr_t> root_vals_;
|
||||||
|
|
||||||
ScopedSignalHandler segv_handler_;
|
ScopedSignalHandler sigsegv_handler_;
|
||||||
|
ScopedSignalHandler sigbus_handler_;
|
||||||
volatile uintptr_t walking_ptr_;
|
volatile uintptr_t walking_ptr_;
|
||||||
Range walking_range_;
|
Range walking_range_;
|
||||||
bool segv_logged_;
|
bool segv_logged_;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "android-base/macros.h"
|
#include "android-base/macros.h"
|
||||||
|
|
||||||
|
#include "Allocator.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
@ -32,17 +33,29 @@ class ScopedSignalHandler {
|
||||||
public:
|
public:
|
||||||
using Fn = std::function<void(ScopedSignalHandler&, int, siginfo_t*, void*)>;
|
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(); }
|
~ScopedSignalHandler() { reset(); }
|
||||||
|
|
||||||
template <class F>
|
template <class F>
|
||||||
void install(int signal, F&& f) {
|
void install(int signal, F&& f) {
|
||||||
if (signal_ != -1) MEM_LOG_ALWAYS_FATAL("ScopedSignalHandler already installed");
|
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 {};
|
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;
|
act.sa_flags = SA_SIGINFO;
|
||||||
|
|
||||||
int ret = sigaction(signal, &act, &old_act_);
|
int ret = sigaction(signal, &act, &old_act_);
|
||||||
|
|
@ -59,19 +72,22 @@ class ScopedSignalHandler {
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
MEM_ALOGE("failed to uninstall segfault handler");
|
MEM_ALOGE("failed to uninstall segfault handler");
|
||||||
}
|
}
|
||||||
handler_ = SignalFn{};
|
|
||||||
|
handler_map_->erase(signal_);
|
||||||
|
if (handler_map_->empty()) {
|
||||||
|
handler_map_.reset();
|
||||||
|
}
|
||||||
signal_ = -1;
|
signal_ = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using SignalFn = std::function<void(int, siginfo_t*, void*)>;
|
using SignalFn = std::function<void(int, siginfo_t*, void*)>;
|
||||||
|
using SignalFnMap = allocator::unordered_map<int, SignalFn>;
|
||||||
DISALLOW_COPY_AND_ASSIGN(ScopedSignalHandler);
|
DISALLOW_COPY_AND_ASSIGN(ScopedSignalHandler);
|
||||||
int signal_;
|
int signal_;
|
||||||
struct sigaction old_act_;
|
struct sigaction old_act_;
|
||||||
// TODO(ccross): to support multiple ScopedSignalHandlers handler_ would need
|
static Allocator<SignalFnMap>::unique_ptr handler_map_;
|
||||||
// to be a static map of signals to handlers, but allocated with Allocator.
|
|
||||||
static SignalFn handler_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue