fix Windows crashes dump upload on BugSplat #LINQT-2384

Try to fix deploy (symbols are not uploaded in deploy, only packaging works with cr)

fix windows ci
This commit is contained in:
Gaelle Braud 2026-02-09 17:21:20 +01:00
parent 8442e37bc2
commit 5b4828aa56
13 changed files with 119 additions and 59 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

@ -181,21 +181,22 @@ win64-ninja-vs2022-scheduled-windows:
rules:
- !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
- if: $PACKAGE_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 +208,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 +245,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 +265,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

@ -314,8 +314,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());
@ -666,6 +669,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

@ -286,6 +286,15 @@ QString Paths::getCrashpadDirPath() {
#endif
}
QString Paths::getCrashpadAttachmentsPath() {
#ifdef HAVE_CRASH_HANDLER
return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) +
Constants::PathCrashpadAttachments);
#else
return "";
#endif
}
QString Paths::getMetricsDirPath() {
return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) +
Constants::PathMetrics);

View file

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

View file

@ -157,8 +157,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>
@ -2260,3 +2261,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

@ -194,6 +194,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

@ -58,13 +58,24 @@ CrashReporter::CrashReporter(QObject *parent) : QObject(parent) {
mAttachments.push_back(base::FilePath(Utils::getNativeString(logFiles + "2.log")));
}
void CrashReporter::start() {
bool CrashReporter::start() {
lInfo() << "[CrashReporter] Starting CrashReporter";
auto config =
linphone::Factory::get()->createConfig(Utils::appStringToCoreString(Paths::getConfigFilePath("", true)));
CrashReporter::enable(SettingsModel::getCrashReporterEnabled(config));
return CrashReporter::enable(SettingsModel::getCrashReporterEnabled(config));
}
void CrashReporter::run() {
bool CrashReporter::run() {
// 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);
@ -72,20 +83,33 @@ void CrashReporter::run() {
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) {
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) return;
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

@ -33,9 +33,9 @@ class CrashReporter : public QObject {
public:
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;
@ -49,4 +49,4 @@ public:
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

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