From 273d4a35a9a95ad6e518e1abf3bb98eff0bcfd2b Mon Sep 17 00:00:00 2001
From: Dale Glass <dale@daleglass.net>
Date: Sun, 16 Jul 2023 21:51:36 +0200
Subject: [PATCH] Store annotations before the crash handler initializes

The crash handler only accepts annotations after it's initializes, but
we may do that late and lose some possibly valuable information, or need
to structure things in an awkward manner.

Add a simple system to store annotations in memory until the crash handler
is running.
---
 .../src/crash-handler/CrashHandler.cpp        | 18 ++++++++++++++++--
 .../src/crash-handler/CrashHandler.h          | 19 +++++++++++++++++--
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/libraries/networking/src/crash-handler/CrashHandler.cpp b/libraries/networking/src/crash-handler/CrashHandler.cpp
index 71ab38ec1a..4dc724fe1c 100644
--- a/libraries/networking/src/crash-handler/CrashHandler.cpp
+++ b/libraries/networking/src/crash-handler/CrashHandler.cpp
@@ -50,6 +50,20 @@ bool CrashHandler::start() {
 
     if ( started ) {
         qCInfo(crash_handler) << "Crash handler started";
+        std::size_t countAdded = 0;
+
+        {
+            std::lock_guard<std::mutex> lock(_annotationsMutex);
+            for(const auto &item : _annotations) {
+                setCrashAnnotation(item.first, item.second);
+            }
+
+            countAdded = _annotations.size();
+            _annotations.clear();
+        }
+
+        qCDebug(crash_handler) << "Forwarded" << countAdded << "annotations";
+
     } else {
         qCWarning(crash_handler) << "Crash handler failed to start";
     }
@@ -94,7 +108,6 @@ void CrashHandler::setToken(const QString &token) {
 
 void CrashHandler::setAnnotation(const std::string &key, const char *value) {
     setAnnotation(key, std::string(value));
-    setCrashAnnotation(key, std::string(value));
 }
 
 void CrashHandler::setAnnotation(const std::string &key, const QString &value) {
@@ -103,7 +116,8 @@ void CrashHandler::setAnnotation(const std::string &key, const QString &value) {
 
 void CrashHandler::setAnnotation(const std::string &key, const std::string &value) {
     if (!isStarted()) {
-        qCWarning(crash_handler) << "Can't set annotation" << QString::fromStdString(key) << "to" << QString::fromStdString(value) << "crash handler not yet started";
+        std::lock_guard<std::mutex> lock(_annotationsMutex);
+        _annotations[key] = value;
         return;
     }
 
diff --git a/libraries/networking/src/crash-handler/CrashHandler.h b/libraries/networking/src/crash-handler/CrashHandler.h
index 3f863326ad..d2e8a4b5b5 100644
--- a/libraries/networking/src/crash-handler/CrashHandler.h
+++ b/libraries/networking/src/crash-handler/CrashHandler.h
@@ -14,6 +14,9 @@
 #include <QObject>
 #include <QCoreApplication>
 #include <SettingHandle.h>
+#include <atomic>
+#include <unordered_map>
+#include <mutex>
 
 
 
@@ -162,6 +165,9 @@ public slots:
      * Annotations add extra information, such as the application's version number,
      * the current user, or any other information of interest.
      *
+     * @note Annotations made before the crash handler are remembered, and sent to the
+     * crash handler as soon as it's initialized.
+     *
      * @param key Key
      * @param value Value
      */
@@ -173,6 +179,9 @@ public slots:
      * Annotations add extra information, such as the application's version number,
      * the current user, or any other information of interest.
      *
+     * @note Annotations made before the crash handler are remembered, and sent to the
+     * crash handler as soon as it's initialized.
+     *
      * @param key Key
      * @param value Value
      */
@@ -184,6 +193,10 @@ public slots:
      * Annotations add extra information, such as the application's version number,
      * the current user, or any other information of interest.
      *
+     * @note Annotations made before the crash handler are remembered, and sent to the
+     * crash handler as soon as it's initialized.
+     *
+     *
      * @param key Key
      * @param value Value
      */
@@ -214,8 +227,10 @@ private:
     void setStarted(bool started) { _crashMonitorStarted = started; }
 
 
-    bool _crashMonitorStarted {false};
-    bool _crashReportingEnabled {false};
+    std::atomic<bool> _crashMonitorStarted {false};
+    std::atomic<bool> _crashReportingEnabled {false};
+    std::unordered_map<std::string, std::string> _annotations{};
+    std::mutex _annotationsMutex{};
 
     QString _path;
     QString _crashUrl;