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.
5 #include "chromecast/crash/linux/minidump_writer.h"
8 #include "base/files/file_util.h"
9 #include "base/logging.h"
10 #include "chromecast/base/path_utils.h"
11 #include "chromecast/base/process_utils.h"
12 #include "chromecast/crash/linux/dump_info.h"
13 #include "chromecast/crash/linux/minidump_generator.h"
15 namespace chromecast
{
19 const char kDumpStateSuffix
[] = ".txt.gz";
21 const int kDefaultDumpIntervalHours
= 24;
22 const int kDefaultMaxDumps
= 5;
23 const int kDefaultMaxRecentDumps
= 5;
25 // Fork and run dumpstate, saving results to minidump_name + ".txt.gz".
26 int DumpState(const std::string
& minidump_name
) {
27 std::vector
<std::string
> argv
;
28 argv
.push_back(GetBinPathASCII("dumpstate").value());
30 argv
.push_back("crash-request");
34 minidump_name
); // dumpstate appends ".txt.gz" to the filename.
37 if (!chromecast::GetAppOutput(argv
, &log
)) {
38 LOG(ERROR
) << "failed to execute dumpstate";
46 MinidumpWriter::MinidumpWriter(MinidumpGenerator
* minidump_generator
,
47 const std::string
& minidump_filename
,
48 const MinidumpParams
& params
,
49 const DumpStateCallback
& dump_state_cb
)
50 : minidump_generator_(minidump_generator
),
51 minidump_path_(minidump_filename
),
53 max_dumps_(kDefaultMaxDumps
),
54 dump_interval_(base::TimeDelta::FromHours(kDefaultDumpIntervalHours
)),
55 max_recent_dumps_(kDefaultMaxRecentDumps
),
56 dump_state_cb_(dump_state_cb
) {
59 MinidumpWriter::MinidumpWriter(MinidumpGenerator
* minidump_generator
,
60 const std::string
& minidump_filename
,
61 const MinidumpParams
& params
)
62 : MinidumpWriter(minidump_generator
,
65 base::Bind(&DumpState
)) {
68 MinidumpWriter::~MinidumpWriter() {
71 int MinidumpWriter::DoWork() {
72 // If path is not absolute, append it to |dump_path_|.
73 if (!minidump_path_
.value().empty() && minidump_path_
.value()[0] != '/')
74 minidump_path_
= dump_path_
.Append(minidump_path_
);
76 // The path should be a file in the |dump_path_| directory.
77 if (dump_path_
!= minidump_path_
.DirName()) {
78 LOG(INFO
) << "The absolute path: " << minidump_path_
.value() << " is not"
79 << "in the correct directory: " << dump_path_
.value();
83 // Query if we are able to write another minidump.
84 if (!CanWriteDump()) {
85 LOG(INFO
) << "Skipping writing of dump due to limits";
89 // Generate a minidump at the specified |minidump_path_|.
90 if (!minidump_generator_
->Generate(minidump_path_
.value())) {
91 LOG(ERROR
) << "Generate minidump failed " << minidump_path_
.value();
95 // Run the dumpstate callback.
96 DCHECK(!dump_state_cb_
.is_null());
97 if (dump_state_cb_
.Run(minidump_path_
.value()) < 0) {
98 LOG(ERROR
) << "DumpState callback failed.";
102 // Add this entry to the lockfile.
103 const DumpInfo
info(minidump_path_
.value(),
104 minidump_path_
.value() + kDumpStateSuffix
,
107 if (AddEntryToLockFile(info
) < 0) {
108 LOG(ERROR
) << "lockfile logging failed";
115 bool MinidumpWriter::CanWriteDump() {
116 const auto& dumps
= GetDumpMetadata();
118 // If no more dumps can be written, return false.
119 if (static_cast<int>(dumps
.size()) >= max_dumps_
)
122 // If too many dumps have been written recently, return false.
123 time_t cur_time
= time(0);
124 int recent_dumps
= 0;
125 for (auto dump
: dumps
) {
126 if (difftime(cur_time
, dump
->dump_time()) <= dump_interval_
.InSecondsF()) {
127 if (++recent_dumps
>= max_recent_dumps_
)
135 } // namespace crash_manager