task_trace.cc 2.8 KB

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