diff options
Diffstat (limited to 'FreeFileSync/Source/RealTimeSync/application.cpp')
-rw-r--r-- | FreeFileSync/Source/RealTimeSync/application.cpp | 84 |
1 files changed, 33 insertions, 51 deletions
diff --git a/FreeFileSync/Source/RealTimeSync/application.cpp b/FreeFileSync/Source/RealTimeSync/application.cpp index 6add53b9..1558ea33 100644 --- a/FreeFileSync/Source/RealTimeSync/application.cpp +++ b/FreeFileSync/Source/RealTimeSync/application.cpp @@ -27,6 +27,7 @@ using namespace zen; using namespace rts; +using fff::FfsExitCode; #ifdef __WXGTK3__ //deprioritize Wayland: see FFS' application.cpp GLOBAL_RUN_ONCE(::gdk_set_allowed_backends("x11,*")); //call *before* gtk_init() @@ -37,29 +38,10 @@ IMPLEMENT_APP(Application) namespace { -using fff::FfsExitCode; - -void notifyAppError(const std::wstring& msg, FfsExitCode rc) +void notifyAppError(const std::wstring& msg) { - //raiseExitCode(exitCode_, rc); - - const std::wstring msgType = [&] - { - switch (rc) - { - //*INDENT-OFF* - case FfsExitCode::success: break; - case FfsExitCode::warning: return _("Warning"); - case FfsExitCode::error: return _("Error"); - case FfsExitCode::aborted: return _("Error"); - case FfsExitCode::exception: return _("An exception occurred"); - //*INDENT-ON* - } - assert(false); - return std::wstring{}; - }(); //error handling strategy unknown and no sync log output available at this point! - std::cerr << utfTo<std::string>(msgType + L": " + msg) + '\n'; + std::cerr << utfTo<std::string>(_("Error") + L": " + msg) + '\n'; //alternative0: std::wcerr: cannot display non-ASCII at all, so why does it exist??? //alternative1: wxSafeShowMessage => NO console output on Debian x86, WTF! //alternative2: wxMessageBox() => works, but we probably shouldn't block during command line usage @@ -71,16 +53,24 @@ bool Application::OnInit() { //do not call wxApp::OnInit() to avoid using wxWidgets command line parser + initExtraLog([](const ErrorLog& log) //don't call functions depending on global state (which might be destroyed already!) + { + std::wstring msg; + for (const LogEntry& e : log) + msg += utfTo<std::wstring>(formatMessage(e)); + trim(msg); + notifyAppError(msg); + }); + try { imageResourcesInit(appendPath(fff::getResourceDirPath(), Zstr("Icons.zip"))); } - catch (const FileError& e) { notifyAppError(e.toString(), FfsExitCode::warning); } - //errors are not really critical in this context + catch (const FileError& e) { logExtraError(e.toString()); } //not critical in this context //GTK should already have been initialized by wxWidgets (see \src\gtk\app.cpp:wxApp::Initialize) #if GTK_MAJOR_VERSION == 2 ::gtk_rc_parse(appendPath(fff::getResourceDirPath(), "Gtk2Styles.rc").c_str()); //fix hang on Ubuntu 19.10 (see FFS's application.cpp) - g_vfs_get_default(); //returns unowned GVfs* + [[maybe_unused]] GVfs* defaultFs = ::g_vfs_get_default(); //not owned by us! #elif GTK_MAJOR_VERSION == 3 auto loadCSS = [&](const char* fileName) @@ -91,14 +81,14 @@ bool Application::OnInit() GError* error = nullptr; ZEN_ON_SCOPE_EXIT(if (error) ::g_error_free(error)); - ::gtk_css_provider_load_from_path(provider, //GtkCssProvider* css_provider, - appendPath(fff::getResourceDirPath(), fileName).c_str(), //const gchar* path, + ::gtk_css_provider_load_from_path(provider, //GtkCssProvider* css_provider + appendPath(fff::getResourceDirPath(), fileName).c_str(), //const gchar* path &error); //GError** error if (error) throw SysError(formatGlibError("gtk_css_provider_load_from_path", error)); - ::gtk_style_context_add_provider_for_screen(::gdk_screen_get_default(), //GdkScreen* screen, - GTK_STYLE_PROVIDER(provider), //GtkStyleProvider* provider, + ::gtk_style_context_add_provider_for_screen(::gdk_screen_get_default(), //GdkScreen* screen + GTK_STYLE_PROVIDER(provider), //GtkStyleProvider* provider GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); //guint priority }; try @@ -112,30 +102,26 @@ bool Application::OnInit() { loadCSS("Gtk3Styles.old.css"); //throw SysError } - catch (const SysError& e2) { notifyAppError(e2.toString(), FfsExitCode::warning); } + catch (const SysError& e3) { logExtraError(_("Error during process initialization.") + L"\n\n" + e3.toString()); } } #else #error unknown GTK version! #endif - try - { - /* we're a GUI app: ignore SIGHUP when the parent terminal quits! (or process is killed!) + /* we're a GUI app: ignore SIGHUP when the parent terminal quits! (or process is killed!) => the FFS launcher will still be killed => fine => macOS: apparently not needed! interestingly the FFS launcher does receive SIGHUP and *is* killed */ - if (sighandler_t oldHandler = ::signal(SIGHUP, SIG_IGN); - oldHandler == SIG_ERR) - THROW_LAST_SYS_ERROR("signal(SIGHUP)"); - else assert(!oldHandler); - } - catch (const SysError& e) { notifyAppError(e.toString(), FfsExitCode::warning); } + if (sighandler_t oldHandler = ::signal(SIGHUP, SIG_IGN); + oldHandler == SIG_ERR) + logExtraError(_("Error during process initialization.") + L"\n\n" + formatSystemError("signal(SIGHUP)", getLastError())); + else assert(!oldHandler); //Windows User Experience Interaction Guidelines: tool tips should have 5s timeout, info tips no timeout => compromise: wxToolTip::Enable(true); //wxWidgets screw-up: wxToolTip::SetAutoPop is no-op if global tooltip window is not yet constructed: wxToolTip::Enable creates it wxToolTip::SetAutoPop(15'000); //https://docs.microsoft.com/en-us/windows/win32/uxguide/ctrl-tooltips-and-infotips - SetAppName(L"RealTimeSync"); + SetAppName(L"RealTimeSync"); //if not set, defaults to executable name try @@ -143,25 +129,21 @@ bool Application::OnInit() fff::localizationInit(appendPath(fff::getResourceDirPath(), Zstr("Languages.zip"))); //throw FileError fff::setLanguage(getProgramLanguage()); //throw FileError } - catch (const FileError& e) { notifyAppError(e.toString(), FfsExitCode::warning); } + catch (const FileError& e) { logExtraError(e.toString()); } auto onSystemShutdown = [](int /*unused*/ = 0) { onSystemShutdownRunTasks(); //it's futile to try and clean up while the process is in full swing (CRASH!) => just terminate! - terminateProcess(static_cast<int>(FfsExitCode::aborted)); + terminateProcess(static_cast<int>(FfsExitCode::cancelled)); }; Bind(wxEVT_QUERY_END_SESSION, [onSystemShutdown](wxCloseEvent& event) { onSystemShutdown(); }); //can veto Bind(wxEVT_END_SESSION, [onSystemShutdown](wxCloseEvent& event) { onSystemShutdown(); }); //can *not* veto - try - { - if (auto /*sighandler_t n.a. on macOS*/ oldHandler = ::signal(SIGTERM, onSystemShutdown);//"graceful" exit requested, unlike SIGKILL - oldHandler == SIG_ERR) - THROW_LAST_SYS_ERROR("signal(SIGTERM)"); - else assert(!oldHandler); - } - catch (const SysError& e) { notifyAppError(e.toString(), FfsExitCode::warning); } + if (auto /*sighandler_t n.a. on macOS*/ oldHandler = ::signal(SIGTERM, onSystemShutdown);//"graceful" exit requested, unlike SIGKILL + oldHandler == SIG_ERR) + logExtraError(_("Error during process initialization.") + L"\n\n" + formatSystemError("signal(SIGTERM)", getLastError())); + else assert(!oldHandler); //Note: app start is deferred: -> see FreeFileSync CallAfter([&] { onEnterEventLoop(); }); @@ -207,7 +189,7 @@ void Application::onEnterEventLoop() } catch (const FileError& e) { - notifyAppError(e.toString(), FfsExitCode::exception); + notifyAppError(e.toString()); } } @@ -240,7 +222,7 @@ void Application::OnUnhandledException() //handles both wxApp::OnInit() + wxApp: } catch (const std::bad_alloc& e) //the only kind of exception we don't want crash dumps for { - notifyAppError(utfTo<std::wstring>(e.what()), FfsExitCode::exception); + notifyAppError(utfTo<std::wstring>(e.what())); terminateProcess(static_cast<int>(FfsExitCode::exception)); } //catch (...) -> Windows: let it crash and create mini dump!!! Linux/macOS: std::exception::what() logged to console |