Fatal error crash doesn't restore old screen mode in linux

Fatal error crash doesn't restore old screen mode in linux

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

Post Reply
User avatar
robed
Posts: 56
Joined: 02 Mar 2006, 03:18

Fatal error crash doesn't restore old screen mode in linux

Post by robed »

Hokay, so Main runs though it's init, and starts up the game, then let's say LoadExtentions fails to find GL_ARB_texture_compress. Well, LoadExtentions sends an error message and then does an exit(0). All good, except that the GL interface is never release. I figured if we move the "Shutdown" function call from SpringApp::Run to SpringApp::~Springapp() we would fix this, exit get's called, the destructor runs, then shutdown releases impotant stuff. Problem is exit won't do that, the destructor is never run.

My fix is to make a SpringApp::ExitFromAnywhere(int retCode) function. I was originaly planing this, but I figured the destructor was a better way to go. Since it doesn't work, we'll have to change all the exit(retCode) calls into mySpringApp->ExitFromAnywhere(retCode); calls. I'll try to find that bug report system and post a fix on it later tonight. It's basically going to look like this:

/rts/System/Main.cpp

Code: Select all

/* Somewhere up top */
SpringApp* g_pMySpringApp = NULL;

class SpringApp /*...*/
{
/* functions */
  void ExitFromAnywhere(int retCode); //Cleanly exit from anywhere durring exicution
/* More stuff, vars and such*/
};

/*later on, say after Shutdown and before main*/

void SpringApp::ExitFromAnywhere(int retCode)
{
  Shutdown();
  exit(retCode);
}

/* in main */
SpringApp Spring
g_pMySpringapp = (*Spring);
Spring.Run(/*stuff*/);
g_pMySpringapp = NULL;
Make the Main.h file for people who need to call exit from anywhere

Code: Select all

/* Main.h */

#ifndef _MAIN_H_
#define _MAIN_H_

extern SpringApp* g_pMySpringApp;

#endif // _MAIN_H_
Now each call to exit(retCode) should be replaced with g_pMySpringapp->ExitFromAnywhere(retCode)

Course there could be other ways of doing this. The main thing here, is that Springapp::Shutdown will get called before exit(retCode)

Other ways include, say a static variable holding the SpringApp instance, and a static function ExitFromAnywhere(), replacing exit with Springapp::ExitFromAnywhere();

Please comment on how yous want this done, and I'll coded it tonight after dinner ;p
User avatar
Das Bruce
Posts: 3544
Joined: 23 Nov 2005, 06:16

Post by Das Bruce »

Mantis.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

Sounds good. The error handling code is entirely messed up anyway, so anything you do to it will make it better :shock:

I'd go with throwing exceptions (std::runtime_error?) though instead of more global classes/functions, so you can cleanly call SpringApp::Shutdown in the catcher and show an error message.

Just make something post a patch in mantis / on the ML, and then discussion can start :wink:
User avatar
robed
Posts: 56
Joined: 02 Mar 2006, 03:18

Post by robed »

I made a post on mantis, and referenced this topic (http://taspring.clan-sy.com/mantis/view.php?id=109. As said before, and in mantis, you need not use my method of getting shutdown to be called, but it cannot be done in the destructor.

Here's the changes:

1) make a file, Main.h (code section to follow)
2) make the modifications to Main.cpp (diff to follow)
3) find any code that has this:

Code: Select all

	exit(0);
Change it to this:

Code: Select all

// Other includes...
#include "System/Main.h"

// more code ...

	// exit(0); is the old way :P
	SpringApp::ExitCleanFromAnywhere(0);

Here's the new truct/rts/System/Main.h:

Code: Select all


#ifndef MAIN_H
#define MAIN_H

#include "StdAfx.h"
#include "Rendering/GL/myGL.h"
#include <GL/glu.h>			// Header File For The GLu32 Library
#include <time.h>
#include <string>
#include <algorithm>
#include <math.h>
#include "Game/PreGame.h"
#include "Game/Game.h"
#include <float.h>
#include "Rendering/glFont.h"
#include "Rendering/Textures/TAPalette.h"
#include "Game/UI/MouseHandler.h"
#include "Platform/ConfigHandler.h"
#include "Game/UI/InfoConsole.h"
#include "Game/GameSetup.h"
#include "Game/CameraController.h"
#include "Net.h"
#include "FileSystem/ArchiveScanner.h"
#include "FileSystem/VFSHandler.h"
#include "Platform/BaseCmd.h"
#include "Game/GameVersion.h"
#include "Platform/errorhandler.h"
#include "creg/creg.h"
#include "bitops.h"
#ifndef NO_LUA
#include "Script/LuaBinder.h"
#endif
#include <SDL.h>
#include <SDL_main.h>
#include "mmgr.h"
#include "Game/UI/NewGuiDefine.h"
#ifdef NEW_GUI
#include "Game/UI/GUI/GUIcontroller.h"
#endif

#ifdef _WIN32
#include "CrashRpt.h"
#include "Platform/Win/win32.h"
#include <winreg.h>
#include <direct.h>
#include <SDL_syswm.h>
#endif

/**
 * @brief Spring App
 * 
 * Main Spring application class launched by main()
 */
class SpringApp
{
public:
	SpringApp (); 					//!< Constructor
	~SpringApp (); 					//!< Destructor

	int Run(int argc, char *argv[]); 		//!< Run game loop
	static void ExitCleanFromAnywhere(int retCode);	//!< Exit the run game loop durring a major error

protected:
	bool Initialize (); 				//!< Initialize app
	void CheckCmdLineFile (int argc,char *argv[]); 	//!< Check command line for files
	bool ParseCmdLine(); 				//!< Parse command line
	void InitVFS (); 				//!< Initialize VFS
	void CreateGameSetup (); 			//!< Creates GameSetup
	bool InitWindow (const char* title); 		//!< Initializes window
	void InitOpenGL (); 				//!< Initializes OpenGL
	bool SetSDLVideoMode(); 			//!< Sets SDL video mode
	void Shutdown (); 				//!< Shuts down application
	int Draw (); 					//!< Repeated draw function
	void UpdateSDLKeys (); 				//!< Update SDL key array

	/**
	 * @brief command line
	 * 
	 * Pointer to instance of commandline parser
	 */
	BaseCmd *cmdline;

	/**
	 * @brief demofile
	 * 
	 * Name of a demofile
	 */
	string demofile;

	/**
	 * @brief startscript
	 * 
	 * Name of a start script
	 */
	string startscript;

	/**
	 * @brief screen width
	 * 
	 * Game screen width
	 */
	int screenWidth;

	/**
	 * @brief screen height
	 * 
	 * Game screen height
	 */
	int screenHeight;

	/**
	 * @brief screen freq
	 * 
	 * Game screen frequency
	 */
	int screenFreq;

	/**
	 * @brief active
	 * 
	 * Whether game is active
	 */
	bool active;

	/**
	 * @brief FSAA
	 * 
	 * Level of fullscreen anti-aliasing
	 */
	bool FSAA;
};

#endif /* MAIN_H */

Make note of the new static void ExitClean... function below "SpringApp::Run"

Now for diff ./modified.trunk/rts/System/Main.cpp ./orig.truck/rts/System/Main.cpp

Code: Select all

7a8,42
> #include "StdAfx.h"
> #include "Rendering/GL/myGL.h"
> #include <GL/glu.h>                   // Header File For The GLu32 Library
> #include <time.h>
> #include <string>
> #include <algorithm>
> #include <math.h>
> #include "Game/PreGame.h"
> #include "Game/Game.h"
> #include <float.h>
> #include "Rendering/glFont.h"
> #include "Rendering/Textures/TAPalette.h"
> #include "Game/UI/MouseHandler.h"
> #include "Platform/ConfigHandler.h"
> #include "Game/UI/InfoConsole.h"
> #include "Game/GameSetup.h"
> #include "Game/CameraController.h"
> #include "Net.h"
> #include "FileSystem/ArchiveScanner.h"
> #include "FileSystem/VFSHandler.h"
> #include "Platform/BaseCmd.h"
> #include "Game/GameVersion.h"
> #include "Platform/errorhandler.h"
> #include "creg/creg.h"
> #include "bitops.h"
> #ifndef NO_LUA
> #include "Script/LuaBinder.h"
> #endif
> #include <SDL.h>
> #include <SDL_main.h>
> #include "mmgr.h"
> #include "Game/UI/NewGuiDefine.h"
> #ifdef NEW_GUI
> #include "Game/UI/GUI/GUIcontroller.h"
> #endif
9,10c44,50
< // Includes and Declairation for Springapp
< #include "Main.h"
---
> #ifdef _WIN32
> #include "CrashRpt.h"
> #include "Platform/Win/win32.h"
> #include <winreg.h>
> #include <direct.h>
> #include <SDL_syswm.h>
> #endif
57,59c97,99
<  * @brief g_pMySpringAppInstance
<  *
<  * Easy way to get access to Springapp instance ->Shutdown() for ExitCleanFromAnywhere()
---
>  * @brief Spring App
>  * 
>  * Main Spring application class launched by main()
61c101,177
< SpringApp* g_pMySpringAppInstance = NULL;
---
> class SpringApp
> {
> public:
>       SpringApp ();                                   //!< Constructor
>       ~SpringApp ();                                  //!< Destructor
> 
>       int Run(int argc, char *argv[]);                //!< Run game loop
> 
> protected:
>       bool Initialize ();                             //!< Initialize app
>       void CheckCmdLineFile (int argc,char *argv[]);  //!< Check command line for files
>       bool ParseCmdLine();                            //!< Parse command line
>       void InitVFS ();                                //!< Initialize VFS
>       void CreateGameSetup ();                        //!< Creates GameSetup
>       bool InitWindow (const char* title);            //!< Initializes window
>       void InitOpenGL ();                             //!< Initializes OpenGL
>       bool SetSDLVideoMode();                         //!< Sets SDL video mode
>       void Shutdown ();                               //!< Shuts down application
>       int Draw ();                                    //!< Repeated draw function
>       void UpdateSDLKeys ();                          //!< Update SDL key array
> 
>       /**
>        * @brief command line
>        * 
>        * Pointer to instance of commandline parser
>        */
>       BaseCmd *cmdline;
> 
>       /**
>        * @brief demofile
>        * 
>        * Name of a demofile
>        */
>       string demofile;
> 
>       /**
>        * @brief startscript
>        * 
>        * Name of a start script
>        */
>       string startscript;
> 
>       /**
>        * @brief screen width
>        * 
>        * Game screen width
>        */
>       int screenWidth;
> 
>       /**
>        * @brief screen height
>        * 
>        * Game screen height
>        */
>       int screenHeight;
> 
>       /**
>        * @brief screen freq
>        * 
>        * Game screen frequency
>        */
>       int screenFreq;
> 
>       /**
>        * @brief active
>        * 
>        * Whether game is active
>        */
>       bool active;
> 
>       /**
>        * @brief FSAA
>        * 
>        * Level of fullscreen anti-aliasing
>        */
>       bool FSAA;
> };
63,66d178
< /**************************
<  * SpringApp definitions: *
<  **************************/
<  
637,651d748
< /**
<  * @brief Clean exit durring a major error
<  *
<  * A call to "exit(retCode)" will not call our destructor
<  * for SpringApp. This function is needed to exit cleanly.
<  */
< /*static*/ void SpringApp::ExitCleanFromAnywhere(int retCode)
< {
<       // Cleanup before an exit
<       g_pMySpringAppInstance->Shutdown();
< 
<       // Hokay, time for an exit
<       exit(retCode);
< }
< 
697d793
<               g_pMySpringAppInstance = &app;
705d800
<       g_pMySpringAppInstance = &app;
Simple enough, I built ran and crashed spring (old video card... that was given to a friend by a friend of the friend because it had lost a fan, and wouldn't work 0.o). My version crashes and restores video modes (ie: releases anything that really needs to be), the old version doesn't.
User avatar
robed
Posts: 56
Joined: 02 Mar 2006, 03:18

Post by robed »

Tobi wrote:I'd go with throwing exceptions (std::runtime_error?) though instead of more global classes/functions, so you can cleanly call SpringApp::Shutdown in the catcher and show an error message.
Hummm, could always add a catch statement to main(...)

Then it's just a case of making, say, a SpringErrorFatal(std:string sErrorMessage, __FILE__, __LINE__); contructor and throw SpringErrorFatal("Something bad", __FILE__, __LINE__);

Course the above won't compile, but yah, looks perty, and all. If yous want I'll go back to the drawing board and fix this up some more, limit the modifications to be made and all ;p with catching you wouldn't need a Main.h, but would probably need a Errors.h and Errors.cpp, then again, that probably be a good thing :P
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

Or we'd just use std::runtime_error, but you can't easily differentiate between difference errors in code in that case.

We already have errorhandler.h IIRC.

I'd do it like this:

Code: Select all

class CSpringException : public std::exception {
  public:
    // printf like constructor
    CSpringException(const char* file, int line, const char* fmt, ...) throw();
    virtual const char* what() const throw() { return msg; }
  private:
    char msg[512];
};
//does msvc already support this??
#define EXCEPTION(fmt, ...) throw CSpringException(__FILE__, __LINE__, fmt, __VA_ARGS__)
then grep for all exit calls and handleerrors calls and replace them

oh and please use unified diff (diff -u) format, it's more common and easier to read imho
User avatar
robed
Posts: 56
Joined: 02 Mar 2006, 03:18

Post by robed »

http://msdn2.microsoft.com/en-us/library/ms177415.aspx

__VA_ARGS__'s work in VC

along with __FILE__ and __LINE__

BTW Most exit(retCode) calls have handleerror(...); calls just above

ie: /trunk/rts/Rendering/GL/myGL.cpp

Code: Select all

// Stuffies ...

void LoadExtensions()
{
        glewInit();

        if(!GLEW_ARB_multitexture || !GLEW_ARB_texture_env_combine){
                handleerror(0,"Needed extension GL_ARB_texture_env_combine not found","Update drivers",0);
                exit(0);
        }

// Stuffies...
I'll leave all the hard work to you :P
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

:roll:
Post Reply

Return to “Engine”