Skip to content

Commit

Permalink
Fixed: Abnormal shutdown causes a crash when setting up busy mode
Browse files Browse the repository at this point in the history
During an abnormal shutdown, we shouldn’t allow busy mode at all.
Also, if all windows are closed, it means GL needs to be shut down
first.

Also improved the main window title composing (using de::String).
  • Loading branch information
skyjake committed Nov 28, 2013
1 parent 8727a45 commit 57f2860
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 68 deletions.
4 changes: 4 additions & 0 deletions doomsday/client/include/busymode.h
Expand Up @@ -37,6 +37,10 @@

#include "dd_share.h"

/// Enables or disables busy mode; if disabled, work is done synchronously
/// in the main thread.
void BusyMode_SetAllowed(boolean allow);

/// @return @c true if specified thread is the current busy task worker.
boolean BusyMode_IsWorkerThread(uint threadId);

Expand Down
18 changes: 10 additions & 8 deletions doomsday/client/include/dd_pinit.h
Expand Up @@ -27,6 +27,16 @@
#include "api_internaldata.h"
#include <de/c_wrapper.h>

#ifdef __CLIENT__
#include <de/String>

/**
* Compose the title for the main window.
* @param title Title text for the window.
*/
de::String DD_ComposeMainWindowTitle();
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -43,14 +53,6 @@ void DD_ShutdownAll(void);

int DD_CheckArg(char const *tag, const char** value);

#ifdef __CLIENT__
/**
* Compose the title for the main window.
* @param title Title text for the window.
*/
void DD_ComposeMainWindowTitle(char* title);
#endif

/**
* Called early on during the startup process so that we can get the console
* online ready for printing ASAP.
Expand Down
54 changes: 32 additions & 22 deletions doomsday/client/src/busymode.cpp
Expand Up @@ -50,6 +50,7 @@ static boolean busyWasIgnoringInput;

#endif // __CLIENT__

static boolean busyModeAllowed = true; ///< Can we enter busy mode?
static boolean busyInited;
static volatile boolean busyDone;

Expand Down Expand Up @@ -203,31 +204,32 @@ static int runTask(BusyTask* task)
DENG_ASSERT(task);

#ifdef __CLIENT__
if(busyModeAllowed)
{
// Let's get busy!
beginTask(task);

// Let's get busy!
beginTask(task);

DENG_ASSERT(eventLoop == 0);

// Run a local event loop since the primary event loop is blocked while
// we're busy. This event loop is able to handle window and input events
// just like the primary loop.
eventLoop = new QEventLoop;
int result = eventLoop->exec();
delete eventLoop;
eventLoop = 0;

// Teardown.
endTask(task);

return result;
DENG_ASSERT(eventLoop == 0);

#else // __SERVER__
// Run a local event loop since the primary event loop is blocked while
// we're busy. This event loop is able to handle window and input events
// just like the primary loop.
eventLoop = new QEventLoop;
int result = eventLoop->exec();
delete eventLoop;
eventLoop = 0;

// Don't bother to start a thread -- non-GUI mode.
return task->worker(task->workerData);
// Teardown.
endTask(task);

return result;
}
else
#endif
{
// Don't bother to start a thread -- non-GUI mode.
return task->worker(task->workerData);
}
}

#ifdef __CLIENT__
Expand All @@ -237,10 +239,18 @@ boolean BusyMode_IsTransitionAnimated(void)
}
#endif

void BusyMode_FreezeGameForBusyMode(void)
void BusyMode_SetAllowed(boolean allow)
{
busyModeAllowed = allow;
}

void BusyMode_FreezeGameForBusyMode(void)
{
#ifdef __CLIENT__
ClientWindow::main().busy().renderTransitionFrame();
if(ClientWindow::hasMain() && busyModeAllowed)
{
ClientWindow::main().busy().renderTransitionFrame();
}
#endif
}

Expand Down
4 changes: 1 addition & 3 deletions doomsday/client/src/clientapp.cpp
Expand Up @@ -277,9 +277,7 @@ void ClientApp::initialize()
Plug_LoadAll();

// Create the main window.
char title[256];
DD_ComposeMainWindowTitle(title);
d->winSys->createWindow()->setWindowTitle(title);
d->winSys->createWindow()->setWindowTitle(DD_ComposeMainWindowTitle());

// Create the input system.
d->inputSys = new InputSystem;
Expand Down
12 changes: 8 additions & 4 deletions doomsday/client/src/con_main.cpp
Expand Up @@ -2210,18 +2210,21 @@ void Con_Error(char const *error, ...)
}

void Con_AbnormalShutdown(char const *message)
{
{
// This is a crash landing, better be safe than sorry.
BusyMode_SetAllowed(false);

Sys_Shutdown();

#ifdef __CLIENT__
DisplayMode_Shutdown();

DENG2_GUI_APP->loop().pause();

// This is an abnormal shutdown, we cannot continue drawing any of the
// windows. (Alternatively could hide/disable drawing of the windows.) Note
// that the app's event loop is running normally while we show the native
// message box below.
// message box below -- if the app windows are not hidden/closed, they might
// receive draw events.
ClientApp::windowSystem().closeAll();
#endif

Expand All @@ -2232,10 +2235,11 @@ void Con_AbnormalShutdown(char const *message)

/// @todo Get the actual output filename (might be a custom one).
Sys_MessageBoxWithDetailsFromFile(MBT_ERROR, DOOMSDAY_NICENAME, message,
"See Details for complete messsage log contents.",
"See Details for complete message log contents.",
de::LogBuffer::appBuffer().outputFile().toUtf8());
}

//Sys_Shutdown();
DD_Shutdown();

// Get outta here.
Expand Down
46 changes: 25 additions & 21 deletions doomsday/client/src/dd_main.cpp
Expand Up @@ -584,6 +584,8 @@ void DD_CreateTextureSchemes()

void DD_ClearRuntimeTextureSchemes()
{
if(Sys_IsShuttingDown()) return;

Textures &textures = App_Textures();

textures.scheme("Flats").clear();
Expand Down Expand Up @@ -1432,6 +1434,10 @@ de::Game &App_CurrentGame()

bool App_ChangeGame(Game &game, bool allowReload)
{
#ifdef __CLIENT__
DENG_ASSERT(ClientWindow::hasMain());
#endif

//LOG_AS("App_ChangeGame");

bool isReload = false;
Expand Down Expand Up @@ -1585,9 +1591,7 @@ bool App_ChangeGame(Game &game, bool allowReload)
Library_ReleaseGames();

#ifdef __CLIENT__
char buf[256];
DD_ComposeMainWindowTitle(buf);
ClientWindow::main().setWindowTitle(buf);
ClientWindow::main().setWindowTitle(DD_ComposeMainWindowTitle());
#endif

if(!DD_IsShuttingDown())
Expand All @@ -1610,8 +1614,7 @@ bool App_ChangeGame(Game &game, bool allowReload)
App::app().setGame(game);

#ifdef __CLIENT__
DD_ComposeMainWindowTitle(buf);
ClientWindow::main().setWindowTitle(buf);
ClientWindow::main().setWindowTitle(DD_ComposeMainWindowTitle());
#endif

/**
Expand Down Expand Up @@ -1684,20 +1687,23 @@ bool App_ChangeGame(Game &game, bool allowReload)
DENG_ASSERT(DD_ActivePluginId() == 0);

#ifdef __CLIENT__
/**
* Clear any input events we may have accumulated during this process.
* @note Only necessary here because we might not have been able to use
* busy mode (which would normally do this for us on end).
*/
DD_ClearEvents();

if(!App_GameLoaded())
{
ClientWindow::main().taskBar().open();
}
else
if(!Sys_IsShuttingDown())
{
ClientWindow::main().console().clearLog();
/**
* Clear any input events we may have accumulated during this process.
* @note Only necessary here because we might not have been able to use
* busy mode (which would normally do this for us on end).
*/
DD_ClearEvents();

if(!App_GameLoaded())
{
ClientWindow::main().taskBar().open();
}
else
{
ClientWindow::main().console().clearLog();
}
}
#endif

Expand Down Expand Up @@ -1815,9 +1821,7 @@ void DD_FinishInitializationAfterWindowReady()
}
else
{
char buf[256];
DD_ComposeMainWindowTitle(buf);
ClientWindow::main().setWindowTitle(buf);
ClientWindow::main().setWindowTitle(DD_ComposeMainWindowTitle());
}
#endif

Expand Down
15 changes: 8 additions & 7 deletions doomsday/client/src/dd_pinit.cpp
Expand Up @@ -42,6 +42,8 @@

#include "api_internaldata.h"

#include <de/String>

/*
* The game imports and exports.
*/
Expand Down Expand Up @@ -71,17 +73,16 @@ int DD_CheckArg(char const *tag, const char** value)
}

#ifdef __CLIENT__
void DD_ComposeMainWindowTitle(char* title)
de::String DD_ComposeMainWindowTitle()
{
de::String title = DOOMSDAY_NICENAME " " DOOMSDAY_VERSION_TEXT;

if(App_GameLoaded() && gx.GetVariable)
{
sprintf(title, "%s - " DOOMSDAY_NICENAME " " DOOMSDAY_VERSION_TEXT,
Str_Text(App_CurrentGame().title()));
}
else
{
strcpy(title, DOOMSDAY_NICENAME " " DOOMSDAY_VERSION_TEXT);
title = de::String(Str_Text(App_CurrentGame().title())) + " - " + title;
}

return title;
}
#endif

Expand Down
2 changes: 2 additions & 0 deletions doomsday/client/src/gl/gl_defer.cpp
Expand Up @@ -298,6 +298,8 @@ void GL_ShutdownDeferredTask(void)

Sys_DestroyMutex(deferredMutex);
deferredMutex = 0;

inited = false;
}

int GL_DeferredTaskCount(void)
Expand Down
3 changes: 2 additions & 1 deletion doomsday/client/src/gl/gl_main.cpp
Expand Up @@ -396,7 +396,7 @@ void GL_ShutdownRefresh()

void GL_Shutdown()
{
if(!initGLOk)
if(!initGLOk || !ClientWindow::hasMain())
return; // Not yet initialized fully.

DENG_ASSERT_IN_MAIN_THREAD();
Expand All @@ -420,6 +420,7 @@ void GL_Shutdown()
FR_Shutdown();
Rend_ModelShutdown();
Sky_Shutdown();
LensFx_Shutdown();
Rend_Reset();

// Ensure the global texture collection is destroyed.
Expand Down
2 changes: 1 addition & 1 deletion doomsday/client/src/gl/gl_texmanager.cpp
Expand Up @@ -940,7 +940,7 @@ void GL_InitTextureManager()

void GL_ResetTextureManager()
{
if(!initedOk) return;
if(Sys_IsShuttingDown() || !initedOk) return;
GL_ReleaseTextures();
GL_PruneTextureVariantSpecifications();
GL_LoadSystemTextures();
Expand Down
2 changes: 2 additions & 0 deletions doomsday/client/src/render/r_draw.cpp
Expand Up @@ -93,6 +93,8 @@ DENG_EXTERN_C void R_SetBorderGfx(struct uri_s const *const *paths)

void R_InitViewWindow(void)
{
if(Sys_IsShuttingDown()) return;

for(int i = 0; i < DDMAXPLAYERS; ++i)
{
R_SetupDefaultViewWindow(i);
Expand Down
6 changes: 5 additions & 1 deletion doomsday/client/src/ui/windowsystem.cpp
Expand Up @@ -20,6 +20,7 @@
#include "ui/windowsystem.h"
#include "ui/clientwindow.h"
#include "ui/style.h"
#include "gl/gl_main.h"
#include "clientapp.h"

#include <QMap>
Expand Down Expand Up @@ -108,7 +109,10 @@ ClientWindow *WindowSystem::find(String const &id) const
}

void WindowSystem::closeAll()
{
{
// We can't get rid of the windows without tearing down GL stuff first.
GL_Shutdown();

qDeleteAll(d->windows.values());
d->windows.clear();
}
Expand Down

0 comments on commit 57f2860

Please sign in to comment.