Skip to content

Commit

Permalink
When using PERF_RECORD_SWITCH, allow ContextSwitchEvent initializat…
Browse files Browse the repository at this point in the history
…ion to fail

The tracee may have died unexpectedly or been killed.

This commit allows the `cont_race` test to consistently pass when the test is run
under all the following conditions:
(a) kernel.perf_event_paranoid = 2
(b) kernel supports PERF_RECORD_SWITCH (Linux kernel >= 6.10)
(c) syscallbuf is enabled (so here we're talking only about `cont_race`
    and NOT `cont_race-no-syscallbuf` which doesn't need switch events anyways)

Without this commit, I noticed the occasional failure in (syscallbuf enabled) `cont_race`:

[FATAL src/PerfCounterBuffers.cc:32:allocate() errno: EBADF] Can't allocate memory for PT DATA area
  • Loading branch information
sidkshatriya authored and rocallahan committed Sep 28, 2024
1 parent 3a5a49e commit cd6d95e
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 8 deletions.
7 changes: 5 additions & 2 deletions src/ContextSwitchEvent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,15 @@ ContextSwitchEventStrategy ContextSwitchEvent::strategy() {
return strat;
}

void ContextSwitchEvent::init(ScopedFd tracee_fd) {
bool ContextSwitchEvent::init(ScopedFd tracee_fd) {
tracee_fd_ = std::move(tracee_fd);
if (strategy() == ContextSwitchEventStrategy::STRATEGY_RECORD_SWITCH) {
mmap_buffer = make_unique<PerfCounterBuffers>();
mmap_buffer->allocate(tracee_fd_, page_size(), 0);
bool ok = false;
mmap_buffer->allocate(tracee_fd_, page_size(), 0, &ok);
return ok;
}
return true;
}

void ContextSwitchEvent::drain_events() {
Expand Down
2 changes: 1 addition & 1 deletion src/ContextSwitchEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace rr {
*/
class ContextSwitchEvent {
public:
void init(ScopedFd tracee_fd);
bool init(ScopedFd tracee_fd);

ScopedFd& tracee_fd() { return tracee_fd_; }

Expand Down
21 changes: 18 additions & 3 deletions src/PerfCounterBuffers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,22 @@ void PerfCounterBuffers::destroy() {
}

void PerfCounterBuffers::allocate(ScopedFd& perf_event_fd,
uint64_t buffer_size, uint64_t aux_size) {
uint64_t buffer_size, uint64_t aux_size, bool *ok) {
this->buffer_size = buffer_size;
if (ok) {
*ok = true;
}

void* base = mmap(NULL, page_size() + buffer_size,
PROT_READ | PROT_WRITE, MAP_SHARED, perf_event_fd, 0);
if (base == MAP_FAILED) {
FATAL() << "Can't allocate memory for PT DATA area";
const auto msg = "Can't allocate memory for PT DATA area";
if (!ok) {
FATAL() << msg;
}
LOG(warn) << msg;
*ok = false;
return;
}
mmap_header = static_cast<struct perf_event_mmap_page*>(base);

Expand All @@ -40,7 +49,13 @@ void PerfCounterBuffers::allocate(ScopedFd& perf_event_fd,
void* aux = mmap(NULL, mmap_header->aux_size, PROT_READ | PROT_WRITE, MAP_SHARED,
perf_event_fd, mmap_header->aux_offset);
if (aux == MAP_FAILED) {
FATAL() << "Can't allocate memory for PT AUX area";
const auto msg = "Can't allocate memory for PT AUX area";
if (!ok) {
FATAL() << msg;
}
LOG(warn) << msg;
*ok = false;
return;
}
mmap_aux_buffer = static_cast<char*>(aux);
}
Expand Down
2 changes: 1 addition & 1 deletion src/PerfCounterBuffers.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class PerfCounterBuffers {
buffer_size(0), packet_in_use(false) {}
~PerfCounterBuffers() { destroy(); }

void allocate(ScopedFd& perf_event_fd, uint64_t buffer_size, uint64_t aux_size);
void allocate(ScopedFd& perf_event_fd, uint64_t buffer_size, uint64_t aux_size, bool *ok = nullptr);
void destroy();

bool allocated() const { return mmap_header != nullptr; }
Expand Down
6 changes: 5 additions & 1 deletion src/RecordTask.cc
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,11 @@ template <typename Arch> void RecordTask::init_buffers_arch() {
desched_fd_child = args.desched_counter_fd;
// Prevent the child from closing this fd
fds->add_monitor(this, desched_fd_child, new PreserveFileMonitor());
desched_fd.init(remote.retrieve_fd(desched_fd_child));
if (!desched_fd.init(remote.retrieve_fd(desched_fd_child))) {
LOG(warn)
<< "ContextSwitchEvent initialization with strategy "
"STRATEGY_RECORD_SWITCH failed. tracee died unexpectedly or killed ??";
}

if (trace_writer().supports_file_data_cloning() &&
session().use_read_cloning()) {
Expand Down

0 comments on commit cd6d95e

Please sign in to comment.