From b6a7541f87c5ed07634eb829af3abdb8239aca18 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 27 Sep 2022 17:05:08 +1000 Subject: GHOST: exit with an error when GHOST cannot be initialized When the GHOST back-end Blender was built with isn't supported, Blender would crash on startup without any useful information. This could happen when building X11 only, then running on Wayland. Now show a list of the GHOST back-ends that were attempted and exit with an error code instead of crashing. --- intern/ghost/GHOST_ISystem.h | 3 +- intern/ghost/intern/GHOST_C-api.cpp | 2 +- intern/ghost/intern/GHOST_ISystem.cpp | 55 ++++++++++++++++++----- source/blender/windowmanager/intern/wm_playanim.c | 8 ++++ source/blender/windowmanager/intern/wm_window.c | 7 +++ 5 files changed, 63 insertions(+), 12 deletions(-) diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index da6233456c3..05ed089809a 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -117,9 +117,10 @@ class GHOST_ISystem { public: /** * Creates the one and only system. + * \param verbose: report back-ends that were attempted no back-end could be loaded. * \return An indication of success. */ - static GHOST_TSuccess createSystem(); + static GHOST_TSuccess createSystem(bool verbose); static GHOST_TSuccess createSystemBackground(); /** diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 0026a33bfc2..69fc6b5f2d0 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -24,7 +24,7 @@ GHOST_SystemHandle GHOST_CreateSystem(void) { - GHOST_ISystem::createSystem(); + GHOST_ISystem::createSystem(true); GHOST_ISystem *system = GHOST_ISystem::getSystem(); return (GHOST_SystemHandle)system; diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp index 13eccf661f5..304d7f0abe6 100644 --- a/intern/ghost/intern/GHOST_ISystem.cpp +++ b/intern/ghost/intern/GHOST_ISystem.cpp @@ -33,8 +33,13 @@ GHOST_ISystem *GHOST_ISystem::m_system = nullptr; GHOST_TBacktraceFn GHOST_ISystem::m_backtrace_fn = nullptr; -GHOST_TSuccess GHOST_ISystem::createSystem() +GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose) { + /* When GHOST fails to start, report the back-ends that were attempted. + * A Verbose argument could be supported in printing isn't always desired. */ + const char *backends_attempted[8] = {nullptr}; + int backends_attempted_num = 0; + GHOST_TSuccess success; if (!m_system) { @@ -52,15 +57,23 @@ GHOST_TSuccess GHOST_ISystem::createSystem() /* Pass. */ #elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND) /* Special case, try Wayland, fall back to X11. */ - try { - m_system = has_wayland_libraries ? new GHOST_SystemWayland() : nullptr; + if (has_wayland_libraries) { + backends_attempted[backends_attempted_num++] = "WAYLAND"; + try { + m_system = new GHOST_SystemWayland(); + } + catch (const std::runtime_error &) { + delete m_system; + m_system = nullptr; + } } - catch (const std::runtime_error &) { - delete m_system; + else { m_system = nullptr; } + if (!m_system) { /* Try to fallback to X11. */ + backends_attempted[backends_attempted_num++] = "X11"; try { m_system = new GHOST_SystemX11(); } @@ -70,6 +83,7 @@ GHOST_TSuccess GHOST_ISystem::createSystem() } } #elif defined(WITH_GHOST_X11) + backends_attempted[backends_attempted_num++] = "X11"; try { m_system = new GHOST_SystemX11(); } @@ -78,14 +92,21 @@ GHOST_TSuccess GHOST_ISystem::createSystem() m_system = nullptr; } #elif defined(WITH_GHOST_WAYLAND) - try { - m_system = has_wayland_libraries ? new GHOST_SystemWayland() : nullptr; + if (has_wayland_libraries) { + backends_attempted[backends_attempted_num++] = "WAYLAND"; + try { + m_system = new GHOST_SystemWayland(); + } + catch (const std::runtime_error &) { + delete m_system; + m_system = nullptr; + } } - catch (const std::runtime_error &) { - delete m_system; + else { m_system = nullptr; } #elif defined(WITH_GHOST_SDL) + backends_attempted[backends_attempted_num++] = "SDL"; try { m_system = new GHOST_SystemSDL(); } @@ -94,10 +115,24 @@ GHOST_TSuccess GHOST_ISystem::createSystem() m_system = nullptr; } #elif defined(WIN32) + backends_attempted[backends_attempted_num++] = "WIN32"; m_system = new GHOST_SystemWin32(); #elif defined(__APPLE__) + backends_attempted[backends_attempted_num++] = "COCOA"; m_system = new GHOST_SystemCocoa(); #endif + + if ((m_system == nullptr) && verbose) { + fprintf(stderr, "GHOST: failed to initialize display for back-end(s): ["); + for (int i = 0; i < backends_attempted_num; i++) { + if (i != 0) { + fprintf(stderr, ", "); + } + fprintf(stderr, "'%s'", backends_attempted[i]); + } + fprintf(stderr, "]\n"); + } + success = m_system != nullptr ? GHOST_kSuccess : GHOST_kFailure; } else { @@ -115,7 +150,7 @@ GHOST_TSuccess GHOST_ISystem::createSystemBackground() if (!m_system) { #if !defined(WITH_HEADLESS) /* Try to create a off-screen render surface with the graphical systems. */ - success = createSystem(); + success = createSystem(false); if (success) { return success; } diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index bb19ba4748f..bf793ee41a0 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -1539,6 +1539,14 @@ static char *wm_main_playanim_intern(int argc, const char **argv) GHOST_SetBacktraceHandler((GHOST_TBacktraceFn)BLI_system_backtrace); g_WS.ghost_system = GHOST_CreateSystem(); + + if (UNLIKELY(g_WS.ghost_system == NULL)) { + /* GHOST will have reported the back-ends that failed to load. */ + fprintf(stderr, "GHOST: unable to initialize, exiting!\n"); + /* This will leak memory, it's preferable to crashing. */ + exit(1); + } + GHOST_AddEventConsumer(g_WS.ghost_system, consumer); playanim_window_open("Blender Animation Player", start_x, start_y, ibuf->x, ibuf->y); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 89bf2b82426..a4f92da2774 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1546,6 +1546,13 @@ void wm_ghost_init(bContext *C) g_system = GHOST_CreateSystem(); + if (UNLIKELY(g_system == NULL)) { + /* GHOST will have reported the back-ends that failed to load. */ + fprintf(stderr, "GHOST: unable to initialize, exiting!\n"); + /* This will leak memory, it's preferable to crashing. */ + exit(1); + } + GHOST_Debug debug = {0}; if (G.debug & G_DEBUG_GHOST) { debug.flags |= GHOST_kDebugDefault; -- cgit v1.2.3