bionic: fix broken end atrace events
When calling write on an FD for trace_marker, it is expected that the pointer passed will be paged into memory. If this isn't the case, the kernel will ignore the string passed and instead write "<faulted>" to the ring buffer. For end events, we were passing a constant string which resides in the rodata section of the ELF file. If this section is paged out, we end up not closing atrace stacks correctly leading to very broken traces. For even more context, see the associated bug. Fix this issue by reading the constant string to the stack first which should mean the string is always paged in. Bug: 197620214 Change-Id: I6a444ac6fe83a6a9fb696c5621e392eca7e9437a
This commit is contained in:
parent
957d6d513e
commit
2aa3f7cb26
|
@ -86,7 +86,21 @@ void bionic_trace_end() {
|
|||
return;
|
||||
}
|
||||
|
||||
TEMP_FAILURE_RETRY(write(trace_marker_fd, "E|", 2));
|
||||
// This code is intentionally "sub-optimal"; do not optimize this by inlining
|
||||
// the E| string into the write.
|
||||
//
|
||||
// This is because if the const char* string passed to write(trace_marker) is not
|
||||
// in resident memory (e.g. the page of the .rodata section that contains it has
|
||||
// been paged out, or the anonymous page that contained a heap-based string is
|
||||
// swapped in zram), the ftrace code will NOT page it in and instead report
|
||||
// <faulted>.
|
||||
//
|
||||
// We "fix" this by putting the string on the stack, which is more unlikely
|
||||
// to be paged out and pass the pointer to that instead.
|
||||
//
|
||||
// See b/197620214 for more context on this.
|
||||
volatile char buf[2]{'E', '|'};
|
||||
TEMP_FAILURE_RETRY(write(trace_marker_fd, const_cast<const char*>(buf), 2));
|
||||
}
|
||||
|
||||
ScopedTrace::ScopedTrace(const char* message) : called_end_(false) {
|
||||
|
|
Loading…
Reference in New Issue