OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 |
| 5 #include "chromecast/crash/minidump_writer.h" |
| 6 |
| 7 #include <cerrno> |
| 8 #include <cstdlib> |
| 9 #include <cstring> |
| 10 #include <fstream> |
| 11 |
| 12 #include "base/logging.h" |
| 13 #include "chromecast/base/path_utils.h" |
| 14 #include "chromecast/base/process_utils.h" |
| 15 #include "chromecast/crash/dump_info.h" |
| 16 #include "chromecast/crash/minidump_generator.h" |
| 17 |
| 18 namespace chromecast { |
| 19 |
| 20 namespace { |
| 21 |
| 22 const char kDumpStateSuffix[] = ".txt.gz"; |
| 23 |
| 24 } // namespace |
| 25 |
| 26 // static |
| 27 int MinidumpWriter::DumpState(const std::string& minidump_name) { |
| 28 std::vector<std::string> argv; |
| 29 argv.push_back(GetBinPathASCII("dumpstate").value()); |
| 30 argv.push_back("-w"); |
| 31 argv.push_back("crash-request"); |
| 32 argv.push_back("-z"); |
| 33 argv.push_back("-o"); |
| 34 argv.push_back( |
| 35 minidump_name); // dumpstate appends ".txt.gz" to the filename. |
| 36 |
| 37 std::string log; |
| 38 if (!chromecast::GetAppOutput(argv, &log)) { |
| 39 LOG(ERROR) << "failed to execute dumpstate"; |
| 40 return -1; |
| 41 } |
| 42 return 0; |
| 43 } |
| 44 |
| 45 MinidumpWriter::MinidumpWriter(MinidumpGenerator* minidump_generator, |
| 46 const std::string& minidump_path, |
| 47 const MinidumpParams& params) |
| 48 : minidump_generator_(minidump_generator), |
| 49 minidump_path_(minidump_path), |
| 50 params_(params) { |
| 51 max_dumps_ = 5; |
| 52 dump_interval_ = 86400; |
| 53 max_recent_dumps_ = 5; |
| 54 max_total_size_ = 500 * 1024 * 1024; |
| 55 } |
| 56 |
| 57 int MinidumpWriter::DoWork() { |
| 58 size_t separator_idx = minidump_path_.find_last_of('/'); |
| 59 if (separator_idx != std::string::npos) { |
| 60 // absolute |
| 61 if (dump_path_.compare(minidump_path_.substr(0, separator_idx))) { |
| 62 LOG(INFO) << "Given path " << minidump_path_ |
| 63 << " does not match dump_path " << dump_path_; |
| 64 return -1; |
| 65 } |
| 66 } else { |
| 67 // relative |
| 68 LOG(ERROR) << "Given path is not absolute"; |
| 69 return -1; |
| 70 } |
| 71 |
| 72 if (!CanWriteDump()) { |
| 73 LOG(INFO) << "Skipping writing of dump due to limits"; |
| 74 return -1; |
| 75 } |
| 76 |
| 77 if (!minidump_generator_->Generate(minidump_path_)) { |
| 78 LOG(ERROR) << "Generate minidump failed " << minidump_path_; |
| 79 return -1; |
| 80 } |
| 81 |
| 82 // write the log |
| 83 if (DumpState(minidump_path_) < 0) { |
| 84 LOG(ERROR) << "Could not dump system log"; |
| 85 } |
| 86 |
| 87 // dumpstate appends .txt.gz to the minidump filename, so maintain this as the |
| 88 // log name. |
| 89 std::string log_str = minidump_path_ + kDumpStateSuffix; |
| 90 |
| 91 // make a new record in the lock file. |
| 92 if (LogLockFile(log_str) < 0) { |
| 93 LOG(ERROR) << "lockfile logging failed"; |
| 94 return -1; |
| 95 } |
| 96 |
| 97 return 0; |
| 98 } |
| 99 |
| 100 bool MinidumpWriter::CanWriteDump() { |
| 101 // Get the current time |
| 102 time_t cur_time = time(0); |
| 103 |
| 104 // Note: since flock is an advisory lock only, it is fine to open the |
| 105 // lockfile again by ifstream. We are guaranteed no race conditions |
| 106 // because this code is only called upon successful flock. |
| 107 std::ifstream in(lockfile_path_.c_str()); |
| 108 if (!in.is_open()) { |
| 109 return false; |
| 110 } |
| 111 |
| 112 std::string record; |
| 113 int num_dumps = 0; |
| 114 int num_recent_dumps = 0; |
| 115 while (std::getline(in, record)) { |
| 116 const DumpInfo info(record); |
| 117 if (info.valid()) { |
| 118 // manual upload entries don't count |
| 119 if (info.crashed_process_dump().length() > 0) { |
| 120 num_dumps++; |
| 121 if (difftime(cur_time, info.dump_time()) <= dump_interval_) { |
| 122 num_recent_dumps++; |
| 123 } |
| 124 } |
| 125 } |
| 126 } |
| 127 |
| 128 in.close(); |
| 129 |
| 130 if (num_dumps >= max_dumps_ || num_recent_dumps >= max_recent_dumps_) { |
| 131 return false; |
| 132 } |
| 133 |
| 134 return true; |
| 135 } |
| 136 |
| 137 int MinidumpWriter::LogLockFile(const std::string& logfile) { |
| 138 // Get the current time |
| 139 time_t cur_time = time(NULL); |
| 140 const DumpInfo info(minidump_path_, logfile, cur_time, params_); |
| 141 if (info.valid()) { |
| 142 std::ofstream out(lockfile_path_.c_str(), std::ios::app); |
| 143 out << info.entry(); |
| 144 return 0; |
| 145 } else { |
| 146 LOG(ERROR) << "entry DumpInfo construction failed"; |
| 147 return -1; |
| 148 } |
| 149 } |
| 150 |
| 151 } // namespace crash_manager |
OLD | NEW |