Skip to content

Commit

Permalink
Merge pull request #8455 from derrod/safe-mode
Browse files Browse the repository at this point in the history
Add Safe Mode
  • Loading branch information
Lain-B committed Jul 22, 2023
2 parents bcbe509 + 396cfdb commit 2f9df13
Show file tree
Hide file tree
Showing 13 changed files with 257 additions and 12 deletions.
4 changes: 4 additions & 0 deletions UI/CMakeLists.txt
Expand Up @@ -108,6 +108,10 @@ foreach(graphics_library IN ITEMS opengl metal d3d11)
endif()
endforeach()

get_property(obs_module_list GLOBAL PROPERTY OBS_MODULES_ENABLED)
list(JOIN obs_module_list "|" SAFE_MODULES)
target_compile_definitions(obs-studio PRIVATE "SAFE_MODULES=\"${SAFE_MODULES}\"")

# cmake-format: off
set_target_properties_obs(obs-studio PROPERTIES FOLDER frontend OUTPUT_NAME "$<IF:$<PLATFORM_ID:Windows>,obs64,obs>")
# cmake-format: on
4 changes: 4 additions & 0 deletions UI/cmake/legacy.cmake
Expand Up @@ -486,6 +486,10 @@ source_group(
unset(_SOURCES)
unset(_UI)

get_property(OBS_MODULE_LIST GLOBAL PROPERTY OBS_MODULE_LIST)
list(JOIN OBS_MODULE_LIST "|" SAFE_MODULES)
target_compile_definitions(obs PRIVATE "SAFE_MODULES=\"${SAFE_MODULES}\"")

define_graphic_modules(obs)
setup_obs_app(obs)
setup_target_resources(obs obs-studio)
Expand Down
11 changes: 11 additions & 0 deletions UI/data/locale/en-US.ini
Expand Up @@ -125,6 +125,15 @@ AlreadyRunning.Title="OBS is already running"
AlreadyRunning.Text="OBS is already running! Unless you meant to do this, please shut down any existing instances of OBS before trying to run a new instance. If you have OBS set to minimize to the system tray, please check to see if it's still running there."
AlreadyRunning.LaunchAnyway="Launch Anyway"

# warning if auto Safe Mode has engaged
AutoSafeMode.Title="Safe Mode"
AutoSafeMode.Text="OBS did not shut down properly during your last session.\n\nWould you like to start in Safe Mode (third-party plugins, scripting, and websockets disabled)?"
AutoSafeMode.LaunchSafe="Run in Safe Mode"
AutoSafeMode.LaunchNormal="Run Normally"
## Restart Option
SafeMode.Restart="Do you want to restart OBS in Safe Mode (third-party plugins, scripting, and websockets disabled)?"
SafeMode.RestartNormal="Do you want to restart OBS in Normal Mode?"

ChromeOS.Title="Unsupported Platform"
ChromeOS.Text="OBS appears to be running inside a ChromeOS container. This platform is unsupported."

Expand Down Expand Up @@ -834,6 +843,8 @@ Basic.MainMenu.Help.Logs.UploadLastLog="Upload &Previous Log File"
Basic.MainMenu.Help.Logs.ViewCurrentLog="&View Current Log"
Basic.MainMenu.Help.CheckForUpdates="Check For Updates"
Basic.MainMenu.Help.Repair="Check File Integrity"
Basic.MainMenu.Help.RestartSafeMode="Restart in Safe Mode"
Basic.MainMenu.Help.RestartNormal="Restart in Normal Mode"
Basic.MainMenu.Help.CrashLogs="Crash &Reports"
Basic.MainMenu.Help.CrashLogs.ShowLogs="&Show Crash Reports"
Basic.MainMenu.Help.CrashLogs.UploadLastLog="Upload &Previous Crash Report"
Expand Down
9 changes: 8 additions & 1 deletion UI/forms/OBSBasic.ui
Expand Up @@ -532,9 +532,11 @@
<addaction name="separator"/>
<addaction name="actionRepair"/>
<addaction name="actionCheckForUpdates"/>
<addaction name="actionRestartSafe"/>
<addaction name="actionShowMacPermissions"/>
<addaction name="separator"/>
<addaction name="actionShowWhatsNew"/>
<addaction name="actionShowAbout"/>
<addaction name="actionShowMacPermissions"/>
<addaction name="separator"/>
</widget>
<widget class="QMenu" name="menuBasic_MainMenu_Edit">
Expand Down Expand Up @@ -2004,6 +2006,11 @@
<string>Basic.MainMenu.Help.Repair</string>
</property>
</action>
<action name="actionRestartSafe">
<property name="text">
<string>Basic.MainMenu.Help.RestartSafeMode</string>
</property>
</action>
<action name="actionInteract">
<property name="text">
<string>Interact</string>
Expand Down
100 changes: 97 additions & 3 deletions UI/obs-app.cpp
Expand Up @@ -87,6 +87,10 @@ static string lastCrashLogFile;

bool portable_mode = false;
bool steam = false;
bool safe_mode = false;
bool disable_3p_plugins = false;
bool unclean_shutdown = false;
bool disable_shutdown_check = false;
static bool multi = false;
static bool log_verbose = false;
static bool unfiltered_log = false;
Expand All @@ -105,6 +109,7 @@ string opt_starting_profile;
string opt_starting_scene;

bool restart = false;
bool restart_safe = false;

QPointer<OBSLogViewer> obsLogViewer;

Expand Down Expand Up @@ -1715,6 +1720,12 @@ bool OBSApp::OBSInit()
QT_VERSION_STR);
blog(LOG_INFO, "Portable mode: %s", portable_mode ? "true" : "false");

if (safe_mode) {
blog(LOG_WARNING, "Safe Mode enabled.");
} else if (disable_3p_plugins) {
blog(LOG_WARNING, "Third-party plugins disabled.");
}

setQuitOnLastWindowClosed(false);

mainWindow = new OBSBasic();
Expand Down Expand Up @@ -2429,6 +2440,10 @@ static int run_program(fstream &logFile, int argc, char *argv[])
blog(LOG_WARNING, "================================");
blog(LOG_WARNING, "User is now running multiple "
"instances of OBS!");
/* Clear unclean_shutdown flag as multiple instances
* running from the same config will lead to a
* false-positive detection.*/
unclean_shutdown = false;
}

/* --------------------------------------- */
Expand All @@ -2453,6 +2468,34 @@ 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.");
}
}

qInstallMessageHandler([](QtMsgType type,
const QMessageLogContext &,
const QString &message) {
Expand Down Expand Up @@ -2540,9 +2583,18 @@ static int run_program(fstream &logFile, int argc, char *argv[])
OBSErrorBox(nullptr, "%s", error);
}

if (restart)
QProcess::startDetached(qApp->arguments()[0],
qApp->arguments());
if (restart || restart_safe) {
auto args = qApp->arguments();
auto executable = args[0];

if (restart_safe) {
args.append("--safe-mode");
} else {
args.removeAll("--safe-mode");
}

QProcess::startDetached(executable, args);
}

return ret;
}
Expand Down Expand Up @@ -3194,6 +3246,32 @@ static void upgrade_settings(void)
os_closedir(dir);
}

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 = GetConfigPathPtr("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)
{
BPtr sentinelPath = GetConfigPathPtr("obs-studio/safe_mode");
os_unlink(sentinelPath);
}

#ifndef _WIN32
void OBSApp::SigIntSignalHandler(int s)
{
Expand Down Expand Up @@ -3281,6 +3359,17 @@ int main(int argc, char *argv[])
} else if (arg_is(argv[i], "--verbose", nullptr)) {
log_verbose = true;

} else if (arg_is(argv[i], "--safe-mode", nullptr)) {
safe_mode = true;

} 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;

Expand Down Expand Up @@ -3347,6 +3436,9 @@ int main(int argc, char *argv[])
"--portable, -p: Use portable mode.\n"
#endif
"--multi, -m: Don't warn when launching multiple instances.\n\n"
"--safe-mode: Run in Safe Mode (disables third-party plugins, scripting, and websockets).\n"
"--only-bundled-plugins: Only load included (first-party) plugins\n"
"--disable-shutdown-check: Disable unclean shutdown detection.\n"
"--verbose: Make log more verbose.\n"
"--always-on-top: Start in 'always on top' mode.\n\n"
"--unfiltered_log: Make log unfiltered.\n\n"
Expand Down Expand Up @@ -3393,6 +3485,7 @@ int main(int argc, char *argv[])
}
#endif

check_safe_mode_sentinel();
upgrade_settings();

fstream logFile;
Expand All @@ -3412,6 +3505,7 @@ 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);
return ret;
Expand Down
3 changes: 3 additions & 0 deletions UI/obs-app.hpp
Expand Up @@ -267,6 +267,8 @@ static inline int GetProfilePath(char *path, size_t size, const char *file)

extern bool portable_mode;
extern bool steam;
extern bool safe_mode;
extern bool disable_3p_plugins;

extern bool opt_start_streaming;
extern bool opt_start_recording;
Expand All @@ -278,6 +280,7 @@ extern bool opt_allow_opengl;
extern bool opt_always_on_top;
extern std::string opt_starting_scene;
extern bool restart;
extern bool restart_safe;

#ifdef _WIN32
extern "C" void install_dll_blocklist_hook(void);
Expand Down

0 comments on commit 2f9df13

Please sign in to comment.