diff --git a/muse b/muse index 8c2f77a598b9..7c049aa5488f 160000 --- a/muse +++ b/muse @@ -1 +1 @@ -Subproject commit 8c2f77a598b9d5b3fa699c5d1f9861dc5e7b1d4a +Subproject commit 7c049aa5488f7c9a481517e85c2755de9d4fdeeb diff --git a/src/app/appfactory.cpp b/src/app/appfactory.cpp index a2868bd0e698..6666e9ab2c5c 100644 --- a/src/app/appfactory.cpp +++ b/src/app/appfactory.cpp @@ -556,6 +556,16 @@ static void addConsoleModules(std::shared_ptr app) static void addAudioPluginRegistrationModules(std::shared_ptr app) { +#ifdef MUSE_MODULE_DIAGNOSTICS + //! NOTE `diagnostics` must be first, because it installs the crash handler. + //! For other modules, the order is (an should be) unimportant. + app->addModule(new muse::diagnostics::DiagnosticsModule()); + + //! NOTE needed by diagnostics module + app->addModule(new muse::actions::ActionsModule()); + app->addModule(new muse::rcommand::RCommandModule()); +#endif + app->addModule(new muse::audio::AudioModule()); #ifdef MUSE_MODULE_AUDIOPLUGINS diff --git a/src/app/cmdoptions.h b/src/app/cmdoptions.h index 00bdf80720bc..01d220dfa0d8 100644 --- a/src/app/cmdoptions.h +++ b/src/app/cmdoptions.h @@ -5,6 +5,7 @@ #include #include "global/io/path.h" +#include "global/types/string.h" #include "global/logger.h" #include "global/internal/cmdoptions.h" @@ -124,6 +125,11 @@ struct MuseScoreCmdOptions : public muse::CmdOptions { muse::io::path_t pluginPath; muse::io::path_t outputFile; } audioPluginRegistration; + + struct CrashDump { + std::optional dir; + std::optional serverUrl; + } crashDump; }; } diff --git a/src/app/internal/commandlineparser.cpp b/src/app/internal/commandlineparser.cpp index 89a7bf6816bf..2ede03775b3a 100644 --- a/src/app/internal/commandlineparser.cpp +++ b/src/app/internal/commandlineparser.cpp @@ -184,6 +184,10 @@ void CommandLineParser::init() "Check an audio plugin for compatibility with the application and register it", "path")); m_parser.addOption(QCommandLineOption("register-audio-plugin-out", "Write audio plugin registration result to file", "path")); + // Crash dumps + m_parser.addOption(internalCommandLineOption("crash-dumps-dir", "Directory where this process writes its crash dumps", "path")); + m_parser.addOption(internalCommandLineOption("crash-server-url", "URL where this process's crash dumps are sent", "url")); + // Internal m_parser.addOption(internalCommandLineOption("score-display-name-override", "Display name to be shown in splash screen for the score that is being opened", "name")); @@ -300,6 +304,14 @@ void CommandLineParser::parse(int argc, char** argv) m_options->audioPluginRegistration.outputFile = fromUserInputPath(m_parser.value("register-audio-plugin-out")); } + if (m_parser.isSet("crash-dumps-dir")) { + m_options->crashDump.dir = fromUserInputPath(m_parser.value("crash-dumps-dir")); + } + + if (m_parser.isSet("crash-server-url")) { + m_options->crashDump.serverUrl = muse::String::fromQString(m_parser.value("crash-server-url")); + } + // Converter mode if (m_parser.isSet("r")) { std::optional val = floatValue("r"); diff --git a/src/app/internal/consoleapp.cpp b/src/app/internal/consoleapp.cpp index c8b161582299..05e84bc38433 100644 --- a/src/app/internal/consoleapp.cpp +++ b/src/app/internal/consoleapp.cpp @@ -80,12 +80,26 @@ void MuseScoreConsoleApp::applyCommandLineOptions(const std::shared_ptrrunMode == IApplication::RunMode::AudioPluginRegistration) { + const std::shared_ptr options = std::dynamic_pointer_cast(opt); + IF_ASSERT_FAILED(options) { return; } - const std::shared_ptr options = std::dynamic_pointer_cast(opt); - IF_ASSERT_FAILED(options) { + if (opt->runMode == IApplication::RunMode::AudioPluginRegistration) { + if (diagnosticsConfiguration()) { + diagnosticsConfiguration()->setSystemCrashReporterForwardingEnabled(false); + + if (options->crashDump.dir.has_value()) { + //! NOTE The spawning process handed us our own pipeline, so that our dumps neither + //! collide with its own nor get uploaded to the wrong project. + diagnosticsConfiguration()->setCrashDumpConfig({ options->crashDump.dir.value(), + options->crashDump.serverUrl.value_or(String{}) }); + } else { + const diagnostics::CrashDumpConfig config = diagnosticsConfiguration()->crashDumpConfig(); + // Keep default directory but empty URL - we don't want plugin-registration events to be sent. + diagnosticsConfiguration()->setCrashDumpConfig({ config.directory, String{} }); + } + } return; } diff --git a/src/app/internal/consoleapp.h b/src/app/internal/consoleapp.h index cce591201af2..a579fc4c74a6 100644 --- a/src/app/internal/consoleapp.h +++ b/src/app/internal/consoleapp.h @@ -40,6 +40,7 @@ #include "testflow/itestflow.h" #include "ui/iuiconfiguration.h" +#include "diagnostics/idiagnosticsconfiguration.h" #include "notation/inotationconfiguration.h" #include "project/iprojectconfiguration.h" #include "playback/isoundprofilesrepository.h" @@ -54,6 +55,7 @@ namespace mu::app { class MuseScoreConsoleApp : public muse::ConsoleApplication { muse::GlobalInject uiConfiguration; + muse::GlobalInject diagnosticsConfiguration; muse::GlobalInject notationConfiguration; muse::GlobalInject projectConfiguration; muse::GlobalInject imagesExportConfiguration;