frontend: Update crash handling and log upload functionality

Updates include:

* Use of CrashHandler to provide automatic uploads of the most recent
crash log if an unclean shutdown was detected and it has not been
uploaded yet.
* Detection and handling of unclean shutdowns is delegated entirely to
the CrashHandler class
* Use of OBSLogReply has been replaced with the LogUploadDialog, which
asks for confirmation before new uploads of log files (confirmation is
skipped for files with available upload URLs already - only available
for crash logs with this change)

Architectural changes:
* OBSApp is the layer responsible for application launch and shutdown
states, as well as crash logs and application logs
* The actual handling is delegated to purpose-made classes which OBSApp
owns instances of
* OBSBasic in turn refers to OBSApp for all this functionality, and can
subscribe/connect to appropriate events exposed by OBSApp to this
purpose
* Implementation details (like the existence of the CrashHandler class)
are not exposed to OBSBasic or the LogUploadDialog

The amount of changes for normal log file upload have been purposefully
limited. A proper refactoring of the application log file handling will
move this code out of OBSBasic as well.
This commit is contained in:
PatTheMav
2025-08-22 15:38:12 -04:00
committed by Ryan Foster
parent e4e3035661
commit de997b1e2f
12 changed files with 245 additions and 380 deletions
+2 -64
View File
@@ -53,15 +53,13 @@ static log_handler_t def_log_handler;
extern string currentLogFile;
extern string lastLogFile;
extern string lastCrashLogFile;
bool portable_mode = false;
bool steam = false;
bool safe_mode = false;
bool disable_3p_plugins = false;
static bool unclean_shutdown = false;
static bool disable_shutdown_check = false;
static bool multi = false;
bool multi = false;
static bool log_verbose = false;
static bool unfiltered_log = false;
bool opt_start_streaming = false;
@@ -405,9 +403,6 @@ static void create_log_file(fstream &logFile)
stringstream dst;
get_last_log(false, "obs-studio/logs", lastLogFile);
#ifdef _WIN32
get_last_log(true, "obs-studio/crashes", lastCrashLogFile);
#endif
currentLogFile = GenerateTimeDateFilename("txt");
dst << "obs-studio/logs/" << currentLogFile.c_str();
@@ -625,26 +620,7 @@ static int run_program(fstream &logFile, int argc, char *argv[])
if (!created_log)
create_log_file(logFile);
if (unclean_shutdown) {
blog(LOG_WARNING, "[Safe Mode] Unclean shutdown detected!");
}
if (unclean_shutdown && !safe_mode) {
QMessageBox mb(QMessageBox::Warning, QTStr("AutoSafeMode.Title"), QTStr("AutoSafeMode.Text"));
QPushButton *launchSafeButton =
mb.addButton(QTStr("AutoSafeMode.LaunchSafe"), QMessageBox::AcceptRole);
QPushButton *launchNormalButton =
mb.addButton(QTStr("AutoSafeMode.LaunchNormal"), QMessageBox::RejectRole);
mb.setDefaultButton(launchNormalButton);
mb.exec();
safe_mode = mb.clickedButton() == launchSafeButton;
if (safe_mode) {
blog(LOG_INFO, "[Safe Mode] User has launched in Safe Mode.");
} else {
blog(LOG_WARNING, "[Safe Mode] User elected to launch normally.");
}
}
program.checkForUncleanShutdown();
qInstallMessageHandler([](QtMsgType type, const QMessageLogContext &, const QString &message) {
switch (type) {
@@ -842,36 +818,6 @@ static inline bool arg_is(const char *arg, const char *long_form, const char *sh
return (long_form && strcmp(arg, long_form) == 0) || (short_form && strcmp(arg, short_form) == 0);
}
static void check_safe_mode_sentinel(void)
{
#ifndef NDEBUG
/* Safe Mode detection is disabled in Debug builds to keep developers
* somewhat sane. */
return;
#else
if (disable_shutdown_check)
return;
BPtr sentinelPath = GetAppConfigPathPtr("obs-studio/safe_mode");
if (os_file_exists(sentinelPath)) {
unclean_shutdown = true;
return;
}
os_quick_write_utf8_file(sentinelPath, nullptr, 0, false);
#endif
}
static void delete_safe_mode_sentinel(void)
{
#ifndef NDEBUG
return;
#else
BPtr sentinelPath = GetAppConfigPathPtr("obs-studio/safe_mode");
os_unlink(sentinelPath);
#endif
}
#ifdef _WIN32
static constexpr char vcRunErrorTitle[] = "Outdated Visual C++ Runtime";
static constexpr char vcRunErrorMsg[] = "OBS Studio requires a newer version of the Microsoft Visual C++ "
@@ -965,7 +911,6 @@ int main(int argc, char *argv[])
for (int i = 1; i < argc; i++) {
if (arg_is(argv[i], "--multi", "-m")) {
multi = true;
disable_shutdown_check = true;
#if ALLOW_PORTABLE_MODE
} else if (arg_is(argv[i], "--portable", "-p")) {
@@ -981,10 +926,6 @@ int main(int argc, char *argv[])
} else if (arg_is(argv[i], "--only-bundled-plugins", nullptr)) {
disable_3p_plugins = true;
} else if (arg_is(argv[i], "--disable-shutdown-check", nullptr)) {
/* This exists mostly to bypass the dialog during development. */
disable_shutdown_check = true;
} else if (arg_is(argv[i], "--always-on-top", nullptr)) {
opt_always_on_top = true;
@@ -1091,8 +1032,6 @@ int main(int argc, char *argv[])
}
#endif
check_safe_mode_sentinel();
fstream logFile;
curl_global_init(CURL_GLOBAL_ALL);
@@ -1109,7 +1048,6 @@ int main(int argc, char *argv[])
log_blocked_dlls();
#endif
delete_safe_mode_sentinel();
blog(LOG_INFO, "Number of memory leaks: %ld", bnum_allocs());
base_set_log_handler(nullptr, nullptr);