mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-08 21:26:04 +00:00
ios: Create a PruneIntermediateDumpsAndCrashReportsThread.
This will prune the database on a daily basis, in accordance with the specified condition. This will also unlock any leftover intermediate dump files. Bug: crashpad:31 Change-Id: I229f8b8006b44d31062fbf73bb9d316d69ab2dcf Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3231618 Commit-Queue: Justin Cohen <justincohen@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
parent
2c45d05875
commit
2d5a30fb17
@ -39,6 +39,8 @@ crashpad_static_library("client") {
|
||||
"ios_handler/in_process_handler.h",
|
||||
"ios_handler/in_process_intermediate_dump_handler.cc",
|
||||
"ios_handler/in_process_intermediate_dump_handler.h",
|
||||
"ios_handler/prune_intermediate_dumps_and_crash_reports_thread.cc",
|
||||
"ios_handler/prune_intermediate_dumps_and_crash_reports_thread.h",
|
||||
"simulate_crash_ios.h",
|
||||
]
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "client/ios_handler/in_process_intermediate_dump_handler.h"
|
||||
#include "client/prune_crash_reports.h"
|
||||
#include "client/settings.h"
|
||||
#include "minidump/minidump_file_writer.h"
|
||||
#include "util/file/directory_reader.h"
|
||||
@ -85,6 +86,14 @@ bool InProcessHandler::Initialize(
|
||||
base_dir_ = database.Append(kPendingSerializediOSDump);
|
||||
CreateDirectory(base_dir_);
|
||||
|
||||
prune_thread_.reset(new PruneIntermediateDumpsAndCrashReportsThread(
|
||||
database_.get(),
|
||||
PruneCondition::GetDefault(),
|
||||
base_dir_,
|
||||
bundle_identifier_and_seperator_,
|
||||
system_data.IsExtension()));
|
||||
prune_thread_->Start();
|
||||
|
||||
if (!OpenNewFile())
|
||||
return false;
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "client/ios_handler/prune_intermediate_dumps_and_crash_reports_thread.h"
|
||||
#include "handler/crash_report_upload_thread.h"
|
||||
#include "snapshot/ios/process_snapshot_ios_intermediate_dump.h"
|
||||
#include "util/ios/ios_intermediate_dump_writer.h"
|
||||
@ -193,6 +194,7 @@ class InProcessHandler {
|
||||
std::unique_ptr<IOSIntermediateDumpWriter> writer_;
|
||||
std::unique_ptr<IOSIntermediateDumpWriter> alternate_mach_writer_;
|
||||
std::unique_ptr<CrashReportUploadThread> upload_thread_;
|
||||
std::unique_ptr<PruneIntermediateDumpsAndCrashReportsThread> prune_thread_;
|
||||
std::unique_ptr<CrashReportDatabase> database_;
|
||||
std::string bundle_identifier_and_seperator_;
|
||||
InitializationStateDcheck initialized_;
|
||||
|
@ -0,0 +1,126 @@
|
||||
// Copyright 2021 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "client/ios_handler/prune_intermediate_dumps_and_crash_reports_thread.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "client/prune_crash_reports.h"
|
||||
#include "util/file/directory_reader.h"
|
||||
#include "util/file/filesystem.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
namespace {
|
||||
|
||||
// The file extension used to indicate a file is locked.
|
||||
constexpr char kLockedExtension[] = ".locked";
|
||||
|
||||
// If the client finds a locked file matching it's own bundle id, unlock it
|
||||
// after 24 hours.
|
||||
constexpr time_t matching_bundle_locked_ttl = 60 * 60 * 24;
|
||||
|
||||
// Unlock any locked intermediate dump after 60 days.
|
||||
constexpr time_t max_locked_ttl = 60 * 60 * 24 * 60;
|
||||
|
||||
// The initial thread delay for applications. Delay the thread's file i/o to
|
||||
// not interfere with application startup.
|
||||
constexpr double app_delay = 60;
|
||||
|
||||
// The initial thread delay for app extensions. Because iOS extensions are often
|
||||
// very short lived, do not wait the full |app_delay|, and instead use a shorter
|
||||
// time.
|
||||
constexpr double extension_delay = 5;
|
||||
|
||||
|
||||
//! \brief Unlocks old intermediate dumps.
|
||||
//!
|
||||
//! This function can unlock (remove the .locked extension) intermediate dumps
|
||||
//! that are either too old to be useful, or are likely leftover dumps from
|
||||
//! clean app exits.
|
||||
//!
|
||||
//! \param[in] pending_path The path to any locked intermediate dump files.
|
||||
//! \param[in] bundle_identifier_and_seperator The identifier for this client,
|
||||
//! used to determine when locked files are considered stale.
|
||||
void UnlockOldIntermediateDumps(base::FilePath pending_path,
|
||||
std::string bundle_identifier_and_seperator) {
|
||||
DirectoryReader reader;
|
||||
std::vector<base::FilePath> files;
|
||||
if (!reader.Open(pending_path)) {
|
||||
return;
|
||||
}
|
||||
base::FilePath file;
|
||||
DirectoryReader::Result result;
|
||||
while ((result = reader.NextFile(&file)) ==
|
||||
DirectoryReader::Result::kSuccess) {
|
||||
if (file.FinalExtension() != kLockedExtension)
|
||||
continue;
|
||||
|
||||
const base::FilePath file_path(pending_path.Append(file));
|
||||
timespec file_time;
|
||||
time_t now = time(nullptr);
|
||||
if (!FileModificationTime(file_path, &file_time)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((file.value().compare(0,
|
||||
bundle_identifier_and_seperator.size(),
|
||||
bundle_identifier_and_seperator) == 0 &&
|
||||
file_time.tv_sec <= now - matching_bundle_locked_ttl) ||
|
||||
(file_time.tv_sec <= now - max_locked_ttl)) {
|
||||
base::FilePath new_path = file_path.RemoveFinalExtension();
|
||||
MoveFileOrDirectory(file_path, new_path);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PruneIntermediateDumpsAndCrashReportsThread::
|
||||
PruneIntermediateDumpsAndCrashReportsThread(
|
||||
CrashReportDatabase* database,
|
||||
std::unique_ptr<PruneCondition> condition,
|
||||
base::FilePath pending_path,
|
||||
std::string bundle_identifier_and_seperator,
|
||||
bool is_extension)
|
||||
: thread_(60 * 60 * 24, this),
|
||||
condition_(std::move(condition)),
|
||||
pending_path_(pending_path),
|
||||
bundle_identifier_and_seperator_(bundle_identifier_and_seperator),
|
||||
initial_work_delay_(is_extension ? extension_delay : app_delay),
|
||||
database_(database) {}
|
||||
|
||||
PruneIntermediateDumpsAndCrashReportsThread::
|
||||
~PruneIntermediateDumpsAndCrashReportsThread() {}
|
||||
|
||||
void PruneIntermediateDumpsAndCrashReportsThread::Start() {
|
||||
thread_.Start(initial_work_delay_);
|
||||
}
|
||||
|
||||
void PruneIntermediateDumpsAndCrashReportsThread::Stop() {
|
||||
thread_.Stop();
|
||||
}
|
||||
|
||||
void PruneIntermediateDumpsAndCrashReportsThread::DoWork(
|
||||
const WorkerThread* thread) {
|
||||
database_->CleanDatabase(60 * 60 * 24 * 3);
|
||||
PruneCrashReportDatabase(database_, condition_.get());
|
||||
if (!clean_old_intermediate_dumps_) {
|
||||
clean_old_intermediate_dumps_ = true;
|
||||
UnlockOldIntermediateDumps(pending_path_, bundle_identifier_and_seperator_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
@ -0,0 +1,102 @@
|
||||
// Copyright 2021 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CRASHPAD_HANDLER_PRUNE_CRASH_REPORTS_THREAD_H_
|
||||
#define CRASHPAD_HANDLER_PRUNE_CRASH_REPORTS_THREAD_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "util/thread/stoppable.h"
|
||||
#include "util/thread/worker_thread.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
class CrashReportDatabase;
|
||||
class PruneCondition;
|
||||
|
||||
//! \brief A thread that periodically prunes crash reports from the database
|
||||
//! using the specified condition, and any leftover locked intermediate
|
||||
//! dumps.
|
||||
//!
|
||||
//! After the thread is started, the database is pruned using the condition
|
||||
//! every 24 hours. Upon calling Start(), the thread waits 5 seconds before
|
||||
//! performing the initial prune operation.
|
||||
//!
|
||||
//! Locked intermediate dump files are unlocked only once, not periodically.
|
||||
//! Locked dumps that match this bundle id can be unlocked if they are over a
|
||||
//! day old. Otherwise, unlock dumps that are over 60 days old.
|
||||
class PruneIntermediateDumpsAndCrashReportsThread
|
||||
: public WorkerThread::Delegate,
|
||||
public Stoppable {
|
||||
public:
|
||||
//! \brief Constructs a new object.
|
||||
//!
|
||||
//! \param[in] database The database to prune crash reports from.
|
||||
//! \param[in] condition The condition used to evaluate crash reports for
|
||||
//! pruning.
|
||||
//! \param[in] pending_path The path to any locked intermediate dump files.
|
||||
//! \param[in] bundle_identifier_and_seperator The identifier for this client,
|
||||
//! used to determine when locked files are considered stale, with a
|
||||
//! seperator at the end to allow for substring searches.
|
||||
PruneIntermediateDumpsAndCrashReportsThread(
|
||||
CrashReportDatabase* database,
|
||||
std::unique_ptr<PruneCondition> condition,
|
||||
base::FilePath pending_path,
|
||||
std::string bundle_identifier_and_seperator,
|
||||
bool is_extension);
|
||||
|
||||
PruneIntermediateDumpsAndCrashReportsThread(
|
||||
const PruneIntermediateDumpsAndCrashReportsThread&) = delete;
|
||||
PruneIntermediateDumpsAndCrashReportsThread& operator=(
|
||||
const PruneIntermediateDumpsAndCrashReportsThread&) = delete;
|
||||
|
||||
~PruneIntermediateDumpsAndCrashReportsThread();
|
||||
|
||||
// Stoppable:
|
||||
|
||||
//! \brief Starts a dedicated pruning thread.
|
||||
//!
|
||||
//! The thread waits before running the initial prune, so as to not interfere
|
||||
//! with any startup-related IO performed by the client.
|
||||
//!
|
||||
//! This method may only be be called on a newly-constructed object or after
|
||||
//! a call to Stop().
|
||||
void Start() override;
|
||||
|
||||
//! \brief Stops the pruning thread.
|
||||
//!
|
||||
//! This method must only be called after Start(). If Start() has been called,
|
||||
//! this method must be called before destroying an object of this class.
|
||||
//!
|
||||
//! This method may be called from any thread other than the pruning thread.
|
||||
//! It is expected to only be called from the same thread that called Start().
|
||||
void Stop() override;
|
||||
|
||||
private:
|
||||
// WorkerThread::Delegate:
|
||||
void DoWork(const WorkerThread* thread) override;
|
||||
|
||||
WorkerThread thread_;
|
||||
std::unique_ptr<PruneCondition> condition_;
|
||||
base::FilePath pending_path_;
|
||||
std::string bundle_identifier_and_seperator_;
|
||||
bool clean_old_intermediate_dumps_;
|
||||
double initial_work_delay_;
|
||||
CrashReportDatabase* database_; // weak
|
||||
};
|
||||
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_HANDLER_PRUNE_CRASH_REPORTS_THREAD_H_
|
@ -33,6 +33,7 @@ class IOSSystemDataCollector {
|
||||
int ProcessorCount() const { return processor_count_; }
|
||||
const std::string& Build() const { return build_; }
|
||||
const std::string& BundleIdentifier() const { return bundle_identifier_; }
|
||||
bool IsExtension() const { return is_extension_; }
|
||||
const std::string& CPUVendor() const { return cpu_vendor_; }
|
||||
bool HasDaylightSavingTime() const { return has_next_daylight_saving_time_; }
|
||||
bool IsDaylightSavingTime() const { return is_daylight_saving_time_; }
|
||||
@ -68,6 +69,7 @@ class IOSSystemDataCollector {
|
||||
int patch_version_;
|
||||
std::string build_;
|
||||
std::string bundle_identifier_;
|
||||
bool is_extension_;
|
||||
std::string machine_description_;
|
||||
int orientation_;
|
||||
int processor_count_;
|
||||
|
@ -79,6 +79,7 @@ IOSSystemDataCollector::IOSSystemDataCollector()
|
||||
build_ = ReadStringSysctlByName("kern.osversion");
|
||||
bundle_identifier_ =
|
||||
base::SysNSStringToUTF8([[NSBundle mainBundle] bundleIdentifier]);
|
||||
is_extension_ = [[NSBundle mainBundle].bundlePath hasSuffix:@"appex"];
|
||||
|
||||
#if defined(ARCH_CPU_X86_64)
|
||||
cpu_vendor_ = ReadStringSysctlByName("machdep.cpu.vendor");
|
||||
|
Loading…
x
Reference in New Issue
Block a user