| OLD | NEW | 
|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "components/arc/metrics/oom_kills_monitor.h" | 5 #include "components/arc/metrics/oom_kills_monitor.h" | 
| 6 | 6 | 
| 7 #include <errno.h> | 7 #include <errno.h> | 
| 8 #include <fcntl.h> | 8 #include <fcntl.h> | 
| 9 #include <stdio.h> | 9 #include <stdio.h> | 
| 10 | 10 | 
| 11 #include <vector> | 11 #include <vector> | 
| 12 | 12 | 
| 13 #include "base/bind.h" | 13 #include "base/bind.h" | 
|  | 14 #include "base/debug/leak_annotations.h" | 
| 14 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" | 
| 15 #include "base/files/scoped_file.h" | 16 #include "base/files/scoped_file.h" | 
| 16 #include "base/location.h" | 17 #include "base/location.h" | 
| 17 #include "base/logging.h" | 18 #include "base/logging.h" | 
|  | 19 #include "base/memory/ptr_util.h" | 
| 18 #include "base/metrics/histogram_macros.h" | 20 #include "base/metrics/histogram_macros.h" | 
| 19 #include "base/posix/safe_strerror.h" | 21 #include "base/posix/safe_strerror.h" | 
| 20 #include "base/sequenced_task_runner.h" | 22 #include "base/sequenced_task_runner.h" | 
| 21 #include "base/strings/string_number_conversions.h" | 23 #include "base/strings/string_number_conversions.h" | 
| 22 #include "base/strings/string_piece.h" | 24 #include "base/strings/string_piece.h" | 
| 23 #include "base/strings/string_split.h" | 25 #include "base/strings/string_split.h" | 
| 24 #include "base/time/time.h" | 26 #include "base/time/time.h" | 
| 25 #include "components/arc/metrics/oom_kills_histogram.h" | 27 #include "components/arc/metrics/oom_kills_histogram.h" | 
| 26 #include "third_party/re2/src/re2/re2.h" | 28 #include "third_party/re2/src/re2/re2.h" | 
| 27 #include "third_party/re2/src/re2/stringpiece.h" | 29 #include "third_party/re2/src/re2/stringpiece.h" | 
| 28 | 30 | 
| 29 namespace arc { | 31 namespace arc { | 
| 30 | 32 | 
| 31 using base::StringPiece; | 33 using base::StringPiece; | 
| 32 | 34 | 
| 33 using base::SequencedWorkerPool; | 35 using base::SequencedWorkerPool; | 
| 34 using base::TimeDelta; | 36 using base::TimeDelta; | 
| 35 | 37 | 
| 36 OomKillsMonitor::OomKillsMonitor() |  | 
| 37     : worker_pool_( |  | 
| 38           new SequencedWorkerPool(1, "oom_kills_monitor")) {} |  | 
| 39 |  | 
| 40 OomKillsMonitor::~OomKillsMonitor() { |  | 
| 41   Stop(); |  | 
| 42 } |  | 
| 43 |  | 
| 44 void OomKillsMonitor::Start() { |  | 
| 45   auto task_runner = worker_pool_->GetTaskRunnerWithShutdownBehavior( |  | 
| 46       SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |  | 
| 47   task_runner->PostTask( |  | 
| 48       FROM_HERE, base::Bind(&OomKillsMonitor::Run, worker_pool_)); |  | 
| 49 } |  | 
| 50 |  | 
| 51 void OomKillsMonitor::Stop() { |  | 
| 52   worker_pool_->Shutdown(); |  | 
| 53 } |  | 
| 54 |  | 
| 55 namespace { | 38 namespace { | 
| 56 | 39 | 
| 57 int64_t GetTimestamp(const StringPiece& line) { | 40 int64_t GetTimestamp(const StringPiece& line) { | 
| 58   std::vector<StringPiece> fields = base::SplitStringPiece( | 41   std::vector<StringPiece> fields = base::SplitStringPiece( | 
| 59       line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 42       line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 
| 60 | 43 | 
| 61   int64_t timestamp = -1; | 44   int64_t timestamp = -1; | 
| 62   // Timestamp is the third field in a line of /dev/kmsg. | 45   // Timestamp is the third field in a line of /dev/kmsg. | 
| 63   if (fields.size() < 3 || !base::StringToInt64(fields[2], ×tamp)) | 46   if (fields.size() < 3 || !base::StringToInt64(fields[2], ×tamp)) | 
| 64     return -1; | 47     return -1; | 
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 147 | 130 | 
| 148     if (GetTimeDelta(line, &last_timestamp, &time_delta)) { | 131     if (GetTimeDelta(line, &last_timestamp, &time_delta)) { | 
| 149       UMA_HISTOGRAM_OOM_KILL_TIME_INTERVAL( | 132       UMA_HISTOGRAM_OOM_KILL_TIME_INTERVAL( | 
| 150           "Arc.LowMemoryKiller.TimeDelta", time_delta); | 133           "Arc.LowMemoryKiller.TimeDelta", time_delta); | 
| 151     } | 134     } | 
| 152   } | 135   } | 
| 153 } | 136 } | 
| 154 | 137 | 
| 155 }  // namespace | 138 }  // namespace | 
| 156 | 139 | 
|  | 140 OomKillsMonitor::Handle::Handle(OomKillsMonitor* outer) : outer_(outer) { | 
|  | 141   DCHECK(outer_); | 
|  | 142 } | 
|  | 143 | 
|  | 144 OomKillsMonitor::Handle::~Handle() { | 
|  | 145   outer_->is_shutting_down_.Set(); | 
|  | 146 } | 
|  | 147 | 
|  | 148 OomKillsMonitor::OomKillsMonitor() { | 
|  | 149   base::SimpleThread::Options non_joinable_options; | 
|  | 150   non_joinable_options.joinable = false; | 
|  | 151   non_joinable_worker_thread_ = base::MakeUnique<base::DelegateSimpleThread>( | 
|  | 152       this, "oom_kills_monitor", non_joinable_options); | 
|  | 153   non_joinable_worker_thread_->Start(); | 
|  | 154 } | 
|  | 155 | 
|  | 156 OomKillsMonitor::~OomKillsMonitor() { | 
|  | 157   // The instance has to be leaked on shutdown as it is referred to by a | 
|  | 158   // non-joinable thread but ~OomKillsMonitor() can't be explicitly deleted as | 
|  | 159   // it overrides ~SimpleThread(), it should nevertheless never be invoked. | 
|  | 160   NOTREACHED(); | 
|  | 161 } | 
|  | 162 | 
| 157 // static | 163 // static | 
| 158 void OomKillsMonitor::Run( | 164 OomKillsMonitor::Handle OomKillsMonitor::StartMonitoring() { | 
| 159     scoped_refptr<base::SequencedWorkerPool> worker_pool) { | 165 #if DCHECK_IS_ON() | 
|  | 166   static volatile bool monitoring_active = false; | 
|  | 167   DCHECK(!monitoring_active); | 
|  | 168   monitoring_active = true; | 
|  | 169 #endif | 
|  | 170 | 
|  | 171   // Instantiate the OomKillsMonitor and its underlying thread. The | 
|  | 172   // OomKillsMonitor itself has to be leaked on shutdown per having a | 
|  | 173   // non-joinable thread associated to its state. The OomKillsMonitor::Handle | 
|  | 174   // will notify the OomKillsMonitor when it is destroyed so that the underlying | 
|  | 175   // thread can at a minimum not do extra work during shutdown. | 
|  | 176   OomKillsMonitor* instance = new OomKillsMonitor; | 
|  | 177   ANNOTATE_LEAKING_OBJECT_PTR(instance); | 
|  | 178   return Handle(instance); | 
|  | 179 } | 
|  | 180 | 
|  | 181 void OomKillsMonitor::Run() { | 
| 160   base::ScopedFILE kmsg_handle( | 182   base::ScopedFILE kmsg_handle( | 
| 161       base::OpenFile(base::FilePath("/dev/kmsg"), "r")); | 183       base::OpenFile(base::FilePath("/dev/kmsg"), "r")); | 
| 162   if (!kmsg_handle) { | 184   if (!kmsg_handle) { | 
| 163     LOG(WARNING) << "Open /dev/kmsg failed: " << base::safe_strerror(errno); | 185     LOG(WARNING) << "Open /dev/kmsg failed: " << base::safe_strerror(errno); | 
| 164     return; | 186     return; | 
| 165   } | 187   } | 
| 166   // Skip kernel messages prior to the instantiation of this object to avoid | 188   // Skip kernel messages prior to the instantiation of this object to avoid | 
| 167   // double reporting. | 189   // double reporting. | 
| 168   fseek(kmsg_handle.get(), 0, SEEK_END); | 190   fseek(kmsg_handle.get(), 0, SEEK_END); | 
| 169 | 191 | 
| 170   static const int kMaxBufSize = 512; | 192   static const int kMaxBufSize = 512; | 
| 171   char buf[kMaxBufSize]; | 193   char buf[kMaxBufSize]; | 
| 172 | 194 | 
| 173   while (fgets(buf, kMaxBufSize, kmsg_handle.get())) { | 195   while (fgets(buf, kMaxBufSize, kmsg_handle.get())) { | 
| 174     if (worker_pool->IsShutdownInProgress()) { | 196     if (is_shutting_down_.IsSet()) { | 
| 175       DVLOG(1) << "Chrome is shutting down, exit now."; | 197       DVLOG(1) << "Chrome is shutting down, exit now."; | 
| 176       break; | 198       break; | 
| 177     } | 199     } | 
| 178     const StringPiece buf_string(buf); | 200     const StringPiece buf_string(buf); | 
| 179     LogOOMKill(buf_string); | 201     LogOOMKill(buf_string); | 
| 180     LogLowMemoryKill(buf_string); | 202     LogLowMemoryKill(buf_string); | 
| 181   } | 203   } | 
| 182 } | 204 } | 
| 183 | 205 | 
| 184 }  // namespace arc | 206 }  // namespace arc | 
| OLD | NEW | 
|---|