fix Windows crashes dump upload on BugSplat #LINQT-2384

Try to fix deploy (symbols are not uploaded in deploy, only packaging works with cr)
This commit is contained in:
Gaelle Braud 2026-02-09 17:21:20 +01:00 committed by gaelle
parent bf786c67a3
commit 7e0a33766b
16 changed files with 941 additions and 881 deletions

View file

@ -102,7 +102,7 @@ macosx-ninja-package:
- if: $PACKAGE_MACOSX
- if: $DEPLOY_MACOSX
variables:
CMAKE_OPTIONS: -DPython3_ROOT_DIR=/opt/bc/pip-packages/ -DENABLE_APP_PACKAGING=ON -DENABLE_GPL_THIRD_PARTIES=OFF -DENABLE_G729=ON -DENABLE_BUGSPLAT_SYMBOLS_UPLOAD=ON -DBUGSPLAT_CLIENT_ID=$BUGSPLAT_CLIENT_ID -DBUGSPLAT_CLIENT_SECRET=$BUGSPLAT_CLIENT_SECRET -DBUGSPLAT_DATABASE=$BUGSPLAT_DATABASE
CMAKE_OPTIONS: -DPython3_ROOT_DIR=/opt/bc/pip-packages/ -DENABLE_APP_PACKAGING=ON -DENABLE_GPL_THIRD_PARTIES=OFF -DENABLE_G729=ON -DBUGSPLAT_CLIENT_ID=$BUGSPLAT_CLIENT_ID -DBUGSPLAT_CLIENT_SECRET=$BUGSPLAT_CLIENT_SECRET -DBUGSPLAT_DATABASE=$BUGSPLAT_DATABASE
RELEASE_FILE: -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$MACOSX_PLATFORM/$APP_FOLDER
extends: macosx-ninja
script:

View file

@ -182,20 +182,20 @@ win64-ninja-vs2022-scheduled-windows:
- !reference [.rules-merge-request-manual, rules]
- if: $NIGHTLY_RELEASE
- if: $PACKAGE_WINDOWS
variables:
CMAKE_OPTIONS: -DENABLE_APP_PACKAGING=YES -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=OFF
RELEASE_FILE: -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$WINDOWS_PLATFORM/$APP_FOLDER
.vs-win64-package-cr:
stage: package
needs: []
rules:
- if: $NIGHTLY_MASTER
- if: $DEPLOY_WINDOWS
variables:
CMAKE_OPTIONS: -DENABLE_APP_PACKAGING=YES -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=OFF -DENABLE_BUGSPLAT_SYMBOLS_UPLOAD=ON -DBUGSPLAT_CLIENT_ID=$BUGSPLAT_CLIENT_ID -DBUGSPLAT_CLIENT_SECRET=$BUGSPLAT_CLIENT_SECRET -DBUGSPLAT_DATABASE=$BUGSPLAT_DATABASE
RELEASE_FILE: -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$WINDOWS_PLATFORM/$APP_FOLDER
# .vs-win64-package-cr:
# stage: package
# needs: []
# rules:
# - if: $NIGHTLY_MASTER
# - if: $DEPLOY_WINDOWS
# variables:
# CMAKE_OPTIONS: -DENABLE_APP_PACKAGING=YES -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=OFF -DENABLE_BUGSPLAT_SYMBOLS_UPLOAD=ON -DBUGSPLAT_CLIENT_ID=$BUGSPLAT_CLIENT_ID -DBUGSPLAT_CLIENT_SECRET=$BUGSPLAT_CLIENT_SECRET -DBUGSPLAT_DATABASE=$BUGSPLAT_DATABASE
# RELEASE_FILE: -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$WINDOWS_PLATFORM/$APP_FOLDER
win64-ninja-vs2022-package-windows:
variables:
CMAKE_GENERATOR: "Ninja"
@ -207,15 +207,15 @@ win64-ninja-vs2022-package-windows:
- .vs-win64-package
#Packaging for deployment (Upload symbols at the same time of the packaging)
win64-ninja-vs2022-package-cr-windows:
variables:
CMAKE_GENERATOR: "Ninja"
CMAKE_ARCHITECTURE: ""
PARALLEL_OPTIONS: ""
extends:
- .windows-vs2022
- .windows-ninja-variables
- .vs-win64-package-cr
# win64-ninja-vs2022-package-cr-windows:
# variables:
# CMAKE_GENERATOR: "Ninja"
# CMAKE_ARCHITECTURE: ""
# PARALLEL_OPTIONS: ""
# extends:
# - .windows-vs2022
# - .windows-ninja-variables
# - .vs-win64-package-cr
#################################################
@ -244,28 +244,6 @@ win64-codesigning:
when: always
expire_in: 1 week
win64-codesigning-cr:
stage: signing
allow_failure: true
extends:
- .windows-codesigning
needs:
- win64-ninja-vs2022-package-cr-windows
variables:
MINGW_TYPE: mingw64
rules:
- if: $NIGHTLY_MASTER
- if: $DEPLOY_WINDOWS
script:
- cd build-desktop/OUTPUT/Packages/
- Invoke-Expression "& ${WINDOWS_SIGN_TOOL} sign /fd SHA256 /t ${WINDOWS_SIGN_TIMESTAMP_URL} /sha1 ${WINDOWS_SIGN_HASH} *.exe"
- 'if (-not ($LastExitCode -eq 0)) {throw "Error: Signature failed"}'
artifacts:
paths:
- build-desktop\OUTPUT\Packages\*
when: always
expire_in: 1 week
#################################################
# DEPLOY
#################################################
@ -286,7 +264,7 @@ win64-ninja-vs2022-upload:
extends:
- .win64-upload
needs:
- win64-codesigning-cr
- win64-codesigning
.win64-plugins-upload:
stage: deploy

View file

@ -244,7 +244,10 @@ if(NOT APPLE OR MONO_ARCH)
add_external()
endif()
if(TARGET Crashpad)
message(DEBUG "Target Crashpad, enable crash handler")
set(HAVE_CRASH_HANDLER 1)
else()
message(DEBUG "Target is not Crashpad, disable crash handler")
endif()
function(add_linphone_app)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # Prevent project from overriding the options we just set here

View file

@ -312,8 +312,11 @@ App::App(int &argc, char *argv[])
mLinphoneThread = new Thread(this);
init();
lInfo() << QStringLiteral("Starting application " APPLICATION_NAME " (bin: " EXECUTABLE_NAME
"). Version:%1 Os:%2 Qt:%3")
lInfo() << QStringLiteral("Starting application %1 %2 %3 %4")
.arg(APPLICATION_NAME)
.arg("(bin:")
.arg(EXECUTABLE_NAME)
.arg("). Version:%1 Os:%2 Qt:%3")
.arg(applicationVersion())
.arg(Utils::getOsProduct())
.arg(qVersion());
@ -664,6 +667,17 @@ void App::initCore() {
QMetaObject::invokeMethod(App::getInstance()->thread(), [this, settings] {
// Initialize DestopTools here to have logs into files in case of errors.
DesktopTools::init();
// CrashReporter must be call after app initialization like names.
#ifdef HAVE_CRASH_HANDLER
lInfo() << log().arg("Start CrashReporter.");
bool status = CrashReporter::start();
if (!status) {
lWarning() << log().arg("CrashReporter could not start.");
}
#else
lWarning() << "[Main] The application doesn't support the CrashReporter.";
#endif
// QML
mEngine = new QQmlApplicationEngine(this);
assert(mEngine);

View file

@ -290,7 +290,16 @@ QString Paths::getLogsDirPath() {
QString Paths::getCrashpadDirPath() {
#ifdef HAVE_CRASH_HANDLER
return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) +
Constants::PathCrashpad);
Constants::PathCrashpad);
#else
return "";
#endif
}
QString Paths::getCrashpadAttachmentsPath() {
#ifdef HAVE_CRASH_HANDLER
return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) +
Constants::PathCrashpadAttachments);
#else
return "";
#endif

View file

@ -44,6 +44,7 @@ QString getFriendsListFilePath();
QString getLimeDatabasePath();
QString getLogsDirPath();
QString getCrashpadDirPath();
QString getCrashpadAttachmentsPath();
QString getMetricsDirPath();
QString getMessageHistoryFilePath();
QString getPackageDataDirPath();

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -158,8 +158,9 @@ public:
static constexpr char PathUserCertificates[] = "/usr-crt/";
#ifdef HAVE_CRASH_HANDLER
static constexpr char PathCrashpad[] = "/crashpad/";
static constexpr char PathCrashpadAttachments[] = "/crashpad/attachments/";
static constexpr char PathCrashpadHandler[] = CRASHPAD_EXECUTABLE_NAME;
static constexpr char BugsplatUrl[] = "https://Linphone.bugsplat.com/post/bp/crash/crashpad.php";
static constexpr char BugsplatUrl[] = "https://" BUGSPLAT_DATABASE ".bugsplat.com/post/bp/crash/crashpad.php";
#endif
static constexpr char PathCallHistoryList[] = "/call-history.db";

View file

@ -39,6 +39,7 @@
#include "tool/providers/AvatarProvider.hpp"
#include <limits.h>
#include <signal.h>
#include <QClipboard>
#include <QCryptographicHash>
@ -2206,3 +2207,9 @@ bool Utils::stringMatchFormat(QString toMatch, QRegularExpression regExp) {
auto match = regExp.match(toMatch);
return match.hasMatch();
}
// Debug
void Utils::forceCrash() {
lInfo() << "throwing segmentation fault for debug";
raise(SIGSEGV);
}

View file

@ -192,6 +192,9 @@ public:
Q_INVOKABLE static bool stringMatchFormat(QString toMatch, QRegularExpression regExp);
// Debug
Q_INVOKABLE static void forceCrash();
// QDir findDirectoryByName(QString startPath, QString name);
static QString getApplicationProduct();

View file

@ -20,28 +20,26 @@
#include "CrashReporter.hpp"
#include "config.h"
#include "tool/Utils.hpp"
#include "tool/Constants.hpp"
#include "core/path/Paths.hpp"
#include "model/setting/SettingsModel.hpp"
#include "tool/Constants.hpp"
#include "tool/Utils.hpp"
#include "client/crash_report_database.h"
#include "client/settings.h"
#include <QSettings>
CrashReporter *CrashReporter::gHandler = nullptr;
CrashReporter* CrashReporter::gHandler = nullptr;
CrashReporter::CrashReporter(QObject * parent): QObject(parent) {
CrashReporter::CrashReporter(QObject *parent) : QObject(parent) {
mHandlerPath = base::FilePath(Utils::getNativeString(Paths::getCrashpadHandlerFilePath()));
mDatabasePath = base::FilePath(Utils::getNativeString(Paths::getCrashpadDirPath()));
mMetricsPath = base::FilePath(Utils::getNativeString(Paths::getMetricsDirPath()));
mBugsplatUrl = Constants::BugsplatUrl;
mAnnotations["format"] = "minidump"; // Required: Crashpad setting to save crash as a minidump
mAnnotations["database"] = BUGSPLAT_DATABASE; // Required: BugSplat database
mAnnotations["product"] = APPLICATION_NAME; // Required: BugSplat appName
mAnnotations["format"] = "minidump"; // Required: Crashpad setting to save crash as a minidump
mAnnotations["database"] = BUGSPLAT_DATABASE; // Required: BugSplat database
mAnnotations["product"] = APPLICATION_NAME; // Required: BugSplat appName
mAnnotations["version"] = APPLICATION_SEMVER;
// annotations["key"] = "Sample key"; // Optional: BugSplat key field
// annotations["user"] = "fred@bugsplat.com"; // Optional: BugSplat user email
@ -49,42 +47,69 @@ CrashReporter::CrashReporter(QObject * parent): QObject(parent) {
// Disable crashpad rate limiting so that all crashes have dmp files
mArguments.push_back("--no-rate-limit");
auto config = linphone::Factory::get()->createConfig(Utils::appStringToCoreString(Paths::getConfigFilePath("", true)));
auto config =
linphone::Factory::get()->createConfig(Utils::appStringToCoreString(Paths::getConfigFilePath("", true)));
// Attachments to be uploaded alongside the crash - default bundle size limit is 20MB
// Crashpad doesn't manage folders. We have to guess the files to be uploaded.
QString logFiles = Paths::getLogsDirPath()+QDir::separator()+EXECUTABLE_NAME;
mAttachments.push_back(base::FilePath(Utils::getNativeString(logFiles+".log")));
QString logFiles = Paths::getLogsDirPath() + QDir::separator() + EXECUTABLE_NAME;
mAttachments.push_back(base::FilePath(Utils::getNativeString(logFiles + ".log")));
mAttachments.push_back(base::FilePath(Utils::getNativeString(logFiles + "1.log")));
mAttachments.push_back(base::FilePath(Utils::getNativeString(logFiles + "2.log")));
}
void CrashReporter::start() {
auto config = linphone::Factory::get()->createConfig(Utils::appStringToCoreString(Paths::getConfigFilePath("", true)));
CrashReporter::enable(SettingsModel::getCrashReporterEnabled(config));
bool CrashReporter::start() {
lInfo() << "[CrashReporter] Starting CrashReporter";
auto config =
linphone::Factory::get()->createConfig(Utils::appStringToCoreString(Paths::getConfigFilePath("", true)));
return CrashReporter::enable(SettingsModel::getCrashReporterEnabled(config));
}
void CrashReporter::run() {
//crashpad::CrashpadClient *client = new crashpad::CrashpadClient();
bool status = mClient.StartHandler(mHandlerPath, mDatabasePath, mMetricsPath, mBugsplatUrl.toStdString(), mAnnotations.toStdMap(), mArguments, true, true, mAttachments);
bool CrashReporter::run() {
if(!status){
// Attachments to be uploaded alongside the crash - default bundle size limit is 20MB
base::FilePath attachment(Utils::getNativeString(Paths::getCrashpadAttachmentsPath()));
#if defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX)
// Crashpad hasn't implemented attachments on OS X yet
mAttachments.push_back(attachment);
#endif
lInfo() << "[CrashReporter] Start handler, handler path =" << Paths::getCrashpadHandlerFilePath()
<< "| database path =" << Paths::getCrashpadDirPath() << "| metrics path =" << Paths::getMetricsDirPath()
<< "bugsplat url =" << mBugsplatUrl;
// crashpad::CrashpadClient *client = new crashpad::CrashpadClient();
bool status = mClient.StartHandler(mHandlerPath, mDatabasePath, mMetricsPath, mBugsplatUrl.toStdString(),
mAnnotations.toStdMap(), mArguments, true, true, mAttachments);
if (!status) {
lWarning() << "[CrashReporter] Failed to start Crashpad handler. Crashes will not be logged.";
} else {
lInfo() << "[CrashReporter] Started Crashpad handler. Database at " << Paths::getCrashpadDirPath();
lInfo() << "[CrashReporter] Started Crashpad handler. Database at" << Paths::getCrashpadDirPath();
lInfo() << "[CrashReporter] Crashes upload url :" << mBugsplatUrl;
}
return status;
}
void CrashReporter::enable(const bool& on) {
if(!gHandler) gHandler = new CrashReporter();
std::unique_ptr<crashpad::CrashReportDatabase> database = crashpad::CrashReportDatabase::Initialize(gHandler->mDatabasePath);
if (database == NULL) return;
bool CrashReporter::enable(const bool &on) {
if (!gHandler) gHandler = new CrashReporter();
lInfo() << "[CrashReporter] Enable CrashReporter" << on;
std::unique_ptr<crashpad::CrashReportDatabase> database =
crashpad::CrashReportDatabase::Initialize(gHandler->mDatabasePath);
if (database == NULL) {
lInfo() << "[CrashReporter] No Crashpad database, return";
return false;
}
crashpad::Settings *settings = database->GetSettings();
if (settings == NULL) return;
if (settings == NULL) {
lInfo() << "[CrashReporter] No Crashpad settings, return";
return false;
}
settings->SetUploadsEnabled(on);
if(on) gHandler->run();
else {
if (on) {
lInfo() << "[CrashReporter] Run Crashpad";
return gHandler->run();
} else {
lInfo() << "[CrashReporter] Crashpad has been deactivated by user.";
return false;
}
}

View file

@ -21,21 +21,21 @@
#ifndef CRASH_REPORTER_H_
#define CRASH_REPORTER_H_
#include <QObject>
#include <QMap>
#include <QObject>
#include <QVector>
#include <string>
#include "client/crashpad_client.h"
// =============================================================================
class CrashReporter : public QObject{
class CrashReporter : public QObject {
public:
CrashReporter(QObject * parent = nullptr);
CrashReporter(QObject *parent = nullptr);
static void start();
static void enable(const bool& on);
void run();
static bool start();
static bool enable(const bool &on);
bool run();
crashpad::CrashpadClient mClient;
std::vector<base::FilePath> mAttachments;
@ -46,7 +46,7 @@ public:
base::FilePath mMetricsPath;
base::FilePath mLogsPath;
QString mBugsplatUrl;
static CrashReporter* gHandler;
static CrashReporter *gHandler;
};
#endif
#endif

View file

@ -568,6 +568,23 @@ Item {
}
}
}
MouseArea {
z: parent.z + 1
anchors.fill: parent
acceptedButtons: Qt.RightButton
onPressAndHold: (mouse) => {
debugPopup.open()
}
PopupButton {
id: debugPopup
visible: false
popup.contentItem: Button {
text: "debug: force crash"
onClicked: UtilsCpp.forceCrash()
}
}
}
}
}
}

View file

@ -171,6 +171,8 @@ if(HAVE_CRASH_HANDLER)
endif()
endif()
endif()
else()
message(DEBUG "No Crash handler, do not configure Crashpad")
endif()
# ==============================================================================