1 // Copyright 2019 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/debug/task_trace.h" 6 7 #include "base/ranges/algorithm.h" 8 #include "build/build_config.h" 9 10 #if BUILDFLAG(IS_ANDROID) 11 #include <android/log.h> 12 #endif // BUILDFLAG(IS_ANDROID) 13 14 #include <iostream> 15 #include <sstream> 16 17 #if BUILDFLAG(IS_ANDROID) 18 #include "base/no_destructor.h" 19 #endif 20 21 #include "base/pending_task.h" 22 #include "base/task/common/task_annotator.h" 23 24 namespace base { 25 namespace debug { 26 namespace { 27 #if BUILDFLAG(IS_ANDROID) 28 // Android sends stdout and stderr to /dev/null; logging should be done through 29 // the __android_log_write() function. Here we create an override of 30 // std::stringbuf that writes to the Android log. 31 class AndroidErrBuffer : public std::stringbuf { 32 protected: sync()33 int sync() override { 34 __android_log_write(ANDROID_LOG_ERROR, "chromium", str().c_str()); 35 return 0; 36 } 37 }; 38 DefaultOutputStream()39std::ostream& DefaultOutputStream() { 40 static NoDestructor<AndroidErrBuffer> buf; 41 static NoDestructor<std::ostream> out(buf.get()); 42 return *out; 43 } 44 #else 45 // Use stderr by default. 46 std::ostream& DefaultOutputStream() { 47 return std::cerr; 48 } 49 #endif // BUILDFLAG(IS_ANDROID) 50 } // namespace 51 TaskTrace()52TaskTrace::TaskTrace() { 53 const PendingTask* current_task = TaskAnnotator::CurrentTaskForThread(); 54 if (!current_task) 55 return; 56 std::array<const void*, PendingTask::kTaskBacktraceLength + 1> task_trace; 57 task_trace[0] = current_task->posted_from.program_counter(); 58 ranges::copy(current_task->task_backtrace, task_trace.begin() + 1); 59 size_t length = 0; 60 while (length < task_trace.size() && task_trace[length]) 61 ++length; 62 if (length == 0) 63 return; 64 stack_trace_.emplace(task_trace.data(), length); 65 trace_overflow_ = current_task->task_backtrace_overflow; 66 } 67 empty() const68bool TaskTrace::empty() const { 69 return !stack_trace_.has_value(); 70 } 71 Print() const72void TaskTrace::Print() const { 73 OutputToStream(&DefaultOutputStream()); 74 } 75 OutputToStream(std::ostream * os) const76void TaskTrace::OutputToStream(std::ostream* os) const { 77 *os << "Task trace:" << std::endl; 78 if (!stack_trace_) { 79 *os << "No active task."; 80 return; 81 } 82 *os << *stack_trace_; 83 if (trace_overflow_) { 84 *os << "Task trace buffer limit hit, update " 85 "PendingTask::kTaskBacktraceLength to increase." 86 << std::endl; 87 } 88 } 89 ToString() const90std::string TaskTrace::ToString() const { 91 std::stringstream stream; 92 OutputToStream(&stream); 93 return stream.str(); 94 } 95 GetAddresses(span<const void * > addresses) const96size_t TaskTrace::GetAddresses(span<const void*> addresses) const { 97 size_t count = 0; 98 if (empty()) { 99 return count; 100 } 101 const void* const* current_addresses = stack_trace_->Addresses(&count); 102 for (size_t i = 0; i < count && i < addresses.size(); ++i) { 103 addresses[i] = current_addresses[i]; 104 } 105 return count; 106 } 107 operator <<(std::ostream & os,const TaskTrace & task_trace)108std::ostream& operator<<(std::ostream& os, const TaskTrace& task_trace) { 109 task_trace.OutputToStream(&os); 110 return os; 111 } 112 113 } // namespace debug 114 } // namespace base 115