Index: third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc |
diff --git a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc |
index 2c2b69b937cdc45545fec3861b91eedd66acb16c..d77cdbadc482ab5bee13e1026869bc9f52c415a3 100644 |
--- a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc |
+++ b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc |
@@ -17,6 +17,7 @@ |
#include <errno.h> |
#include <time.h> |
+#include <algorithm> |
#include <map> |
#include <memory> |
#include <vector> |
@@ -29,12 +30,15 @@ |
#include "snapshot/module_snapshot.h" |
#include "util/file/file_reader.h" |
#include "util/misc/metrics.h" |
-#include "util/misc/uuid.h" |
#include "util/net/http_body.h" |
#include "util/net/http_multipart_builder.h" |
#include "util/net/http_transport.h" |
#include "util/stdlib/map_insert.h" |
+#if defined(OS_MACOSX) |
+#include "handler/mac/file_limit_annotation.h" |
+#endif // OS_MACOSX |
+ |
namespace crashpad { |
namespace { |
@@ -139,15 +143,19 @@ class CallRecordUploadAttempt { |
CrashReportUploadThread::CrashReportUploadThread(CrashReportDatabase* database, |
const std::string& url, |
+ bool watch_pending_reports, |
bool rate_limit, |
bool upload_gzip) |
: url_(url), |
- // Check for pending reports every 15 minutes, even in the absence of a |
- // signal from the handler thread. This allows for failed uploads to be |
- // retried periodically, and for pending reports written by other |
- // processes to be recognized. |
- thread_(15 * 60, this), |
+ // When watching for pending reports, check every 15 minutes, even in the |
+ // absence of a signal from the handler thread. This allows for failed |
+ // uploads to be retried periodically, and for pending reports written by |
+ // other processes to be recognized. |
+ thread_(watch_pending_reports ? 15 * 60.0 : WorkerThread::kIndefiniteWait, |
+ this), |
+ known_pending_report_uuids_(), |
database_(database), |
+ watch_pending_reports_(watch_pending_reports), |
rate_limit_(rate_limit), |
upload_gzip_(upload_gzip) { |
} |
@@ -156,18 +164,43 @@ CrashReportUploadThread::~CrashReportUploadThread() { |
} |
void CrashReportUploadThread::Start() { |
- thread_.Start(0); |
+ thread_.Start(watch_pending_reports_ ? 0.0 : WorkerThread::kIndefiniteWait); |
} |
void CrashReportUploadThread::Stop() { |
thread_.Stop(); |
} |
-void CrashReportUploadThread::ReportPending() { |
+void CrashReportUploadThread::ReportPending(const UUID& report_uuid) { |
+ known_pending_report_uuids_.PushBack(report_uuid); |
thread_.DoWorkNow(); |
} |
void CrashReportUploadThread::ProcessPendingReports() { |
+ std::vector<UUID> known_report_uuids = known_pending_report_uuids_.Drain(); |
+ for (const UUID& report_uuid : known_report_uuids) { |
+ CrashReportDatabase::Report report; |
+ if (database_->LookUpCrashReport(report_uuid, &report) != |
+ CrashReportDatabase::kNoError) { |
+ continue; |
+ } |
+ |
+ ProcessPendingReport(report); |
+ |
+ // Respect Stop() being called after at least one attempt to process a |
+ // report. |
+ if (!thread_.is_running()) { |
+ return; |
+ } |
+ } |
+ |
+ // Known pending reports are always processed (above). The rest of this |
+ // function is concerned with scanning for pending reports not already known |
+ // to this thread. |
+ if (!watch_pending_reports_) { |
+ return; |
+ } |
+ |
std::vector<CrashReportDatabase::Report> reports; |
if (database_->GetPendingReports(&reports) != CrashReportDatabase::kNoError) { |
// The database is sick. It might be prudent to stop trying to poke it from |
@@ -178,6 +211,15 @@ void CrashReportUploadThread::ProcessPendingReports() { |
} |
for (const CrashReportDatabase::Report& report : reports) { |
+ if (std::find(known_report_uuids.begin(), |
+ known_report_uuids.end(), |
+ report.uuid) != known_report_uuids.end()) { |
+ // An attempt to process the report already occurred above. The report is |
+ // still pending, so upload must have failed. Don’t retry it immediately, |
+ // it can wait until at least the next pass through this method. |
+ continue; |
+ } |
+ |
ProcessPendingReport(report); |
// Respect Stop() being called after at least one attempt to process a |
@@ -190,6 +232,10 @@ void CrashReportUploadThread::ProcessPendingReports() { |
void CrashReportUploadThread::ProcessPendingReport( |
const CrashReportDatabase::Report& report) { |
+#if defined(OS_MACOSX) |
+ RecordFileLimitAnnotation(); |
+#endif // OS_MACOSX |
+ |
Settings* const settings = database_->GetSettings(); |
bool uploads_enabled; |
@@ -252,9 +298,12 @@ void CrashReportUploadThread::ProcessPendingReport( |
break; |
case CrashReportDatabase::kBusyError: |
+ case CrashReportDatabase::kReportNotFound: |
+ // Someone else may have gotten to it first. If they’re working on it now, |
+ // this will be kBusyError. If they’ve already finished with it, it’ll be |
+ // kReportNotFound. |
return; |
- case CrashReportDatabase::kReportNotFound: |
case CrashReportDatabase::kFileSystemError: |
case CrashReportDatabase::kDatabaseError: |
// In these cases, SkipReportUpload() might not work either, but it’s best |