OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/chromeos/system_logs/debug_log_writer.h" | 5 #include "chrome/browser/chromeos/system_logs/debug_log_writer.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
12 #include "base/callback.h" | 12 #include "base/callback.h" |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "base/files/file.h" | 14 #include "base/files/file.h" |
15 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
| 16 #include "base/lazy_instance.h" |
16 #include "base/process/kill.h" | 17 #include "base/process/kill.h" |
17 #include "base/process/launch.h" | 18 #include "base/process/launch.h" |
18 #include "base/task_scheduler/post_task.h" | 19 #include "base/task_scheduler/post_task.h" |
19 #include "base/threading/sequenced_worker_pool.h" | |
20 #include "chrome/common/logging_chrome.h" | 20 #include "chrome/common/logging_chrome.h" |
21 #include "chromeos/dbus/dbus_thread_manager.h" | 21 #include "chromeos/dbus/dbus_thread_manager.h" |
22 #include "chromeos/dbus/debug_daemon_client.h" | 22 #include "chromeos/dbus/debug_daemon_client.h" |
23 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
24 | 24 |
25 namespace chromeos { | 25 namespace chromeos { |
26 | 26 |
27 namespace { | 27 namespace { |
28 | 28 |
29 // Callback for returning status of executed external command. | 29 // Callback for returning status of executed external command. |
30 typedef base::Callback<void(bool succeeded)> CommandCompletionCallback; | 30 typedef base::Callback<void(bool succeeded)> CommandCompletionCallback; |
31 | 31 |
32 const char kGzipCommand[] = "/bin/gzip"; | 32 const char kGzipCommand[] = "/bin/gzip"; |
33 const char kTarCommand[] = "/bin/tar"; | 33 const char kTarCommand[] = "/bin/tar"; |
34 | 34 |
35 scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunner( | 35 struct DebugLogWriterTaskRunner { |
36 const std::string sequence_name) { | 36 const scoped_refptr<base::SequencedTaskRunner> task_runner = |
37 base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool(); | 37 base::CreateSequencedTaskRunnerWithTraits( |
38 return pool->GetSequencedTaskRunnerWithShutdownBehavior( | 38 {base::MayBlock(), base::TaskPriority::BACKGROUND, |
39 pool->GetNamedSequenceToken(sequence_name), | 39 base::TaskShutdownBehavior::BLOCK_SHUTDOWN}); |
40 base::SequencedWorkerPool::BLOCK_SHUTDOWN); | 40 }; |
41 } | 41 |
| 42 base::LazyInstance<DebugLogWriterTaskRunner>::Leaky g_sequenced_task_runner = |
| 43 LAZY_INSTANCE_INITIALIZER; |
42 | 44 |
43 // Called upon completion of |WriteDebugLogToFile|. Closes file | 45 // Called upon completion of |WriteDebugLogToFile|. Closes file |
44 // descriptor, deletes log file in the case of failure and calls | 46 // descriptor, deletes log file in the case of failure and calls |
45 // |callback|. | 47 // |callback|. |
46 void WriteDebugLogToFileCompleted( | 48 void WriteDebugLogToFileCompleted( |
47 const base::FilePath& file_path, | 49 const base::FilePath& file_path, |
48 const std::string& sequence_token_name, | 50 const std::string& sequence_token_name, |
49 const DebugLogWriter::StoreLogsCallback& callback, | 51 const DebugLogWriter::StoreLogsCallback& callback, |
50 bool succeeded) { | 52 bool succeeded) { |
51 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 53 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
52 if (!succeeded) { | 54 if (!succeeded) { |
53 bool posted = GetSequencedTaskRunner(sequence_token_name)->PostTaskAndReply( | 55 bool posted = g_sequenced_task_runner.Get().task_runner->PostTaskAndReply( |
54 FROM_HERE, | 56 FROM_HERE, |
55 base::Bind(base::IgnoreResult(&base::DeleteFile), file_path, false), | 57 base::Bind(base::IgnoreResult(&base::DeleteFile), file_path, false), |
56 base::Bind(callback, file_path, false)); | 58 base::Bind(callback, file_path, false)); |
57 DCHECK(posted); | 59 DCHECK(posted); |
58 return; | 60 return; |
59 } | 61 } |
60 if (!callback.is_null()) | 62 if (!callback.is_null()) |
61 callback.Run(file_path, true); | 63 callback.Run(file_path, true); |
62 } | 64 } |
63 | 65 |
(...skipping 10 matching lines...) Expand all Loading... |
74 << ", " | 76 << ", " |
75 << "error: " << file->error_details(); | 77 << "error: " << file->error_details(); |
76 return; | 78 return; |
77 } | 79 } |
78 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->DumpDebugLogs( | 80 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->DumpDebugLogs( |
79 should_compress, file->GetPlatformFile(), | 81 should_compress, file->GetPlatformFile(), |
80 base::Bind(&WriteDebugLogToFileCompleted, file_path, sequence_token_name, | 82 base::Bind(&WriteDebugLogToFileCompleted, file_path, sequence_token_name, |
81 callback)); | 83 callback)); |
82 | 84 |
83 // Close the file on an IO-allowed thread. | 85 // Close the file on an IO-allowed thread. |
84 GetSequencedTaskRunner(sequence_token_name) | 86 g_sequenced_task_runner.Get().task_runner->DeleteSoon(FROM_HERE, |
85 ->PostTask(FROM_HERE, | 87 file.release()); |
86 base::Bind(&base::DeletePointer<base::File>, file.release())); | |
87 } | 88 } |
88 | 89 |
89 // Runs command with its parameters as defined in |argv|. | 90 // Runs command with its parameters as defined in |argv|. |
90 // Upon completion, it will report command run outcome via |callback| on the | 91 // Upon completion, it will report command run outcome via |callback| on the |
91 // same thread from where it was initially called from. | 92 // same thread from where it was initially called from. |
92 void RunCommand(const std::vector<std::string>& argv, | 93 void RunCommand(const std::vector<std::string>& argv, |
93 const CommandCompletionCallback& callback) { | 94 const CommandCompletionCallback& callback) { |
94 base::Process process = base::LaunchProcess(argv, base::LaunchOptions()); | 95 base::Process process = base::LaunchProcess(argv, base::LaunchOptions()); |
95 if (!process.IsValid()) { | 96 if (!process.IsValid()) { |
96 LOG(ERROR) << "Failed to execute command " << argv[0]; | 97 LOG(ERROR) << "Failed to execute command " << argv[0]; |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 void StartLogRetrieval(const base::FilePath& file_name_template, | 221 void StartLogRetrieval(const base::FilePath& file_name_template, |
221 bool should_compress, | 222 bool should_compress, |
222 const std::string& sequence_token_name, | 223 const std::string& sequence_token_name, |
223 const DebugLogWriter::StoreLogsCallback& callback) { | 224 const DebugLogWriter::StoreLogsCallback& callback) { |
224 base::FilePath file_path = | 225 base::FilePath file_path = |
225 logging::GenerateTimestampedName(file_name_template, base::Time::Now()); | 226 logging::GenerateTimestampedName(file_name_template, base::Time::Now()); |
226 | 227 |
227 int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE; | 228 int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE; |
228 std::unique_ptr<base::File> file(new base::File); | 229 std::unique_ptr<base::File> file(new base::File); |
229 base::File* file_ptr = file.get(); | 230 base::File* file_ptr = file.get(); |
230 GetSequencedTaskRunner(sequence_token_name) | 231 g_sequenced_task_runner.Get().task_runner->PostTaskAndReply( |
231 ->PostTaskAndReply( | 232 FROM_HERE, |
232 FROM_HERE, base::Bind(&InitializeLogFile, base::Unretained(file_ptr), | 233 base::Bind(&InitializeLogFile, base::Unretained(file_ptr), file_path, |
233 file_path, flags), | 234 flags), |
234 base::Bind(&WriteDebugLogToFile, base::Passed(&file), | 235 base::Bind(&WriteDebugLogToFile, base::Passed(&file), sequence_token_name, |
235 sequence_token_name, file_path, should_compress, | 236 file_path, should_compress, callback)); |
236 callback)); | |
237 } | 237 } |
238 | 238 |
239 const char kDefaultSequenceName[] = "DebugLogWriter"; | 239 const char kDefaultSequenceName[] = "DebugLogWriter"; |
240 | 240 |
241 } // namespace | 241 } // namespace |
242 | 242 |
243 // static. | 243 // static. |
244 void DebugLogWriter::StoreLogs(const base::FilePath& fileshelf, | 244 void DebugLogWriter::StoreLogs(const base::FilePath& fileshelf, |
245 bool should_compress, | 245 bool should_compress, |
246 const StoreLogsCallback& callback) { | 246 const StoreLogsCallback& callback) { |
(...skipping 18 matching lines...) Expand all Loading... |
265 fileshelf.Append(FILE_PATH_LITERAL("combined-logs.tar")); | 265 fileshelf.Append(FILE_PATH_LITERAL("combined-logs.tar")); |
266 | 266 |
267 // Get system logs from /var/log first, then add user-specific stuff. | 267 // Get system logs from /var/log first, then add user-specific stuff. |
268 StartLogRetrieval(file_path, | 268 StartLogRetrieval(file_path, |
269 false, | 269 false, |
270 sequence_token_name, | 270 sequence_token_name, |
271 base::Bind(&OnSystemLogsAdded, callback)); | 271 base::Bind(&OnSystemLogsAdded, callback)); |
272 } | 272 } |
273 | 273 |
274 } // namespace chromeos | 274 } // namespace chromeos |
OLD | NEW |