Added CanBeDeleted class, which implements a timeout function. It is
used to make sure that (in this case) the NewsManager thread does not need the file manager anymore when stk exists (which can only happen on very very quick exists, and slow downloads). This avoids a potential crash that the NewsManager thread could access the file manager after the file manager was deleted.
This commit is contained in:
parent
9c1e371803
commit
c62cc7fbaa
@ -49,9 +49,10 @@ NewsManager::~NewsManager()
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** This function initialises the data for the news manager. It starts a
|
/** This function initialises the data for the news manager. It starts a
|
||||||
* separate thread to execute downloadNews() - which (if necessary) the
|
* separate thread to execute downloadNews() - which (if necessary) downaloads
|
||||||
* news.xml file and updating the list of news messages. It also initialises
|
* the news.xml file and updates the list of news messages. It also
|
||||||
* the addons manager (which can trigger another download of news.xml).
|
* initialises the addons manager (which can trigger another download of
|
||||||
|
* news.xml).
|
||||||
* \param force_refresh Re-download news.xml, even if
|
* \param force_refresh Re-download news.xml, even if
|
||||||
*/
|
*/
|
||||||
void NewsManager::init(bool force_refresh)
|
void NewsManager::init(bool force_refresh)
|
||||||
@ -194,6 +195,10 @@ void* NewsManager::downloadNews(void *obj)
|
|||||||
delete xml;
|
delete xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We can't finish stk (esp. delete the file manager) before
|
||||||
|
// this part of the code is reached (since otherwise the file
|
||||||
|
// manager might be access after it was deleted).
|
||||||
|
me->setCanBeDeleted();
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
return 0; // prevent warning
|
return 0; // prevent warning
|
||||||
} // downloadNews
|
} // downloadNews
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <irrString.h>
|
#include <irrString.h>
|
||||||
using namespace irr;
|
using namespace irr;
|
||||||
|
|
||||||
|
#include "utils/can_be_deleted.hpp"
|
||||||
#include "utils/synchronised.hpp"
|
#include "utils/synchronised.hpp"
|
||||||
|
|
||||||
class XMLNode;
|
class XMLNode;
|
||||||
@ -32,7 +33,7 @@ class XMLNode;
|
|||||||
/**
|
/**
|
||||||
* \ingroup addonsgroup
|
* \ingroup addonsgroup
|
||||||
*/
|
*/
|
||||||
class NewsManager
|
class NewsManager : public CanBeDeleted
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static NewsManager *m_news_manager;
|
static NewsManager *m_news_manager;
|
||||||
|
@ -211,7 +211,10 @@ Window get_toplevel_parent(Display* display, Window window)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
/** If the position of the window should be remembered, store it in the config
|
||||||
|
* file.
|
||||||
|
* \post The user config file must still be saved!
|
||||||
|
*/
|
||||||
void IrrDriver::updateConfigIfRelevant()
|
void IrrDriver::updateConfigIfRelevant()
|
||||||
{
|
{
|
||||||
if (!UserConfigParams::m_fullscreen &&
|
if (!UserConfigParams::m_fullscreen &&
|
||||||
@ -241,7 +244,6 @@ void IrrDriver::updateConfigIfRelevant()
|
|||||||
{
|
{
|
||||||
UserConfigParams::m_window_x = x;
|
UserConfigParams::m_window_x = x;
|
||||||
UserConfigParams::m_window_y = y;
|
UserConfigParams::m_window_y = y;
|
||||||
user_config->saveConfig();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -265,11 +267,10 @@ void IrrDriver::updateConfigIfRelevant()
|
|||||||
{
|
{
|
||||||
UserConfigParams::m_window_x = wx;
|
UserConfigParams::m_window_x = wx;
|
||||||
UserConfigParams::m_window_y = wy;
|
UserConfigParams::m_window_y = wy;
|
||||||
user_config->saveConfig();
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
} // updateConfigIfRelevant
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Gets a list of supported video modes from the irrlicht device. This data
|
/** Gets a list of supported video modes from the irrlicht device. This data
|
||||||
|
39
src/main.cpp
39
src/main.cpp
@ -1375,13 +1375,6 @@ int main(int argc, char *argv[] )
|
|||||||
|
|
||||||
/* Program closing...*/
|
/* Program closing...*/
|
||||||
|
|
||||||
if(user_config)
|
|
||||||
{
|
|
||||||
// In case that abort is triggered before user_config exists
|
|
||||||
if (UserConfigParams::m_crashed) UserConfigParams::m_crashed = false;
|
|
||||||
user_config->saveConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_WIIUSE
|
#ifdef ENABLE_WIIUSE
|
||||||
if(wiimote_manager)
|
if(wiimote_manager)
|
||||||
delete wiimote_manager;
|
delete wiimote_manager;
|
||||||
@ -1433,11 +1426,16 @@ static void cleanSuperTuxKart()
|
|||||||
|
|
||||||
delete main_loop;
|
delete main_loop;
|
||||||
|
|
||||||
irr_driver->updateConfigIfRelevant();
|
|
||||||
|
|
||||||
if(Online::RequestManager::isRunning())
|
if(Online::RequestManager::isRunning())
|
||||||
Online::RequestManager::get()->stopNetworkThread();
|
Online::RequestManager::get()->stopNetworkThread();
|
||||||
|
|
||||||
|
irr_driver->updateConfigIfRelevant();
|
||||||
|
AchievementsManager::destroy();
|
||||||
|
Referee::cleanup();
|
||||||
|
if(ReplayPlay::get()) ReplayPlay::destroy();
|
||||||
|
if(race_manager) delete race_manager;
|
||||||
|
|
||||||
|
|
||||||
//delete in reverse order of what they were created in.
|
//delete in reverse order of what they were created in.
|
||||||
//see InitTuxkart()
|
//see InitTuxkart()
|
||||||
Online::RequestManager::deallocate();
|
Online::RequestManager::deallocate();
|
||||||
@ -1445,12 +1443,6 @@ static void cleanSuperTuxKart()
|
|||||||
Online::ProfileManager::destroy();
|
Online::ProfileManager::destroy();
|
||||||
GUIEngine::DialogQueue::deallocate();
|
GUIEngine::DialogQueue::deallocate();
|
||||||
|
|
||||||
AchievementsManager::destroy();
|
|
||||||
Referee::cleanup();
|
|
||||||
|
|
||||||
if(ReplayPlay::get()) ReplayPlay::destroy();
|
|
||||||
if(race_manager) delete race_manager;
|
|
||||||
NewsManager::deallocate();
|
|
||||||
if(addons_manager) delete addons_manager;
|
if(addons_manager) delete addons_manager;
|
||||||
NetworkManager::kill();
|
NetworkManager::kill();
|
||||||
|
|
||||||
@ -1471,6 +1463,14 @@ static void cleanSuperTuxKart()
|
|||||||
PlayerManager::destroy();
|
PlayerManager::destroy();
|
||||||
if(unlock_manager) delete unlock_manager;
|
if(unlock_manager) delete unlock_manager;
|
||||||
|
|
||||||
|
// Wait (up to 2 seconds) for the news manager to be ready to be deleted,
|
||||||
|
// i.e. make sure it does not need the file_manager anymore (which will
|
||||||
|
// get deleted in cleanUserConfig).
|
||||||
|
if(!NewsManager::get()->waitForReadyToDeleted(2.0f))
|
||||||
|
{
|
||||||
|
Log::info("NewsManager", "News manager not stopping, exiting anyway.");
|
||||||
|
}
|
||||||
|
NewsManager::deallocate();
|
||||||
cleanUserConfig();
|
cleanUserConfig();
|
||||||
|
|
||||||
StateManager::deallocate();
|
StateManager::deallocate();
|
||||||
@ -1485,7 +1485,14 @@ static void cleanUserConfig()
|
|||||||
{
|
{
|
||||||
if(stk_config) delete stk_config;
|
if(stk_config) delete stk_config;
|
||||||
if(translations) delete translations;
|
if(translations) delete translations;
|
||||||
if(user_config) delete user_config;
|
if (user_config)
|
||||||
|
{
|
||||||
|
// In case that abort is triggered before user_config exists
|
||||||
|
if (UserConfigParams::m_crashed) UserConfigParams::m_crashed = false;
|
||||||
|
user_config->saveConfig();
|
||||||
|
delete user_config;
|
||||||
|
}
|
||||||
|
|
||||||
if(file_manager) delete file_manager;
|
if(file_manager) delete file_manager;
|
||||||
if(irr_driver) delete irr_driver;
|
if(irr_driver) delete irr_driver;
|
||||||
}
|
}
|
||||||
|
68
src/utils/can_be_deleted.hpp
Executable file
68
src/utils/can_be_deleted.hpp
Executable file
@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2010-2013 Joerg Henrichs
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#ifndef HEADER_CAN_BE_DELETED
|
||||||
|
#define HEADER_CAN_BE_DELETED
|
||||||
|
|
||||||
|
#include "utils/log.hpp"
|
||||||
|
#include "utils/synchronised.hpp"
|
||||||
|
#include "utils/time.hpp"
|
||||||
|
|
||||||
|
/** A simple class that a
|
||||||
|
*/
|
||||||
|
class CanBeDeleted
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Synchronised<bool> m_can_be_deleted;
|
||||||
|
public:
|
||||||
|
/** Set this instance to be not ready to be deleted. */
|
||||||
|
CanBeDeleted() { m_can_be_deleted.setAtomic(false); }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Sets this instance to be ready to be deleted. */
|
||||||
|
void setCanBeDeleted() {m_can_be_deleted.setAtomic(true); }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Waits at most t seconds for this class to be ready to be deleted.
|
||||||
|
* \return true if the class is ready, false in case of a time out.
|
||||||
|
*/
|
||||||
|
bool waitForReadyToDeleted(float waiting_time)
|
||||||
|
{
|
||||||
|
if (m_can_be_deleted.getAtomic()) return true;
|
||||||
|
double start = StkTime::getRealTime();
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
if(m_can_be_deleted.getAtomic())
|
||||||
|
{
|
||||||
|
Log::verbose("Thread",
|
||||||
|
"Waited %lf for thread to become deleteable.",
|
||||||
|
StkTime::getRealTime()-start);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
StkTime::sleep(10);
|
||||||
|
if(StkTime::getRealTime() - start > waiting_time)
|
||||||
|
{
|
||||||
|
Log::verbose("Thread", "Waited for more than %f seconds for "
|
||||||
|
"thread to become deleteable",
|
||||||
|
waiting_time);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // while 1
|
||||||
|
} // waitForReadyToDeleted
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
}; // CanBeDeleted
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user