Commit 46281da2 authored by Bkg2k's avatar Bkg2k

Catch exceptions from critical codepath

parent 9724dfc1
......@@ -81,53 +81,61 @@ FileData* findOrCreateFile(SystemData* system, const boost::filesystem::path& pa
void parseGamelist(SystemData* system, FileData::StringMap& doppelgangerWatcher)
{
bool trustGamelist = RecalboxConf::getInstance()->get("emulationstation.gamelistonly") == "1";
std::string xmlpath = system->getGamelistPath(false);
if(!boost::filesystem::exists(xmlpath))
return;
LOG(LogInfo) << "Parsing XML file \"" << xmlpath << "\"...";
MetadataDescriptor::Tree gameList;
try
{
pt::read_xml(xmlpath, gameList, 0, std::locale("en_US.UTF8"));
}
catch(std::exception& e)
{
LOG(LogError) << "Could not parse " << xmlpath <<" file!";
LOG(LogError) << e.what();
return;
}
bool trustGamelist = RecalboxConf::getInstance()->get("emulationstation.gamelistonly") == "1";
std::string xmlpath = system->getGamelistPath(false);
fs::path relativeTo = system->getStartPath();
fs::path path;
for (const auto& fileNode : gameList.get_child("gameList"))
{
ItemType type;
if (fileNode.first == "game") type = ItemType::Game;
else if (fileNode.first == "folder") type = ItemType::Folder;
else continue; // Unknown node
if(!boost::filesystem::exists(xmlpath))
return;
const MetadataDescriptor::Tree& children = fileNode.second;
path = resolvePath(children.get("path", ""), relativeTo, false);
LOG(LogInfo) << "Parsing XML file \"" << xmlpath << "\"...";
if(!trustGamelist && !boost::filesystem::exists(path))
MetadataDescriptor::Tree gameList;
try
{
LOG(LogWarning) << "File \"" << path << "\" does not exist! Ignoring.";
continue;
pt::read_xml(xmlpath, gameList, 0, std::locale("en_US.UTF8"));
}
FileData* file = findOrCreateFile(system, path, type, trustGamelist, doppelgangerWatcher);
if(!file)
catch(std::exception& e)
{
LOG(LogError) << "Error finding/creating FileData for \"" << path << "\", skipping.";
continue;
LOG(LogError) << "Could not parse " << xmlpath <<" file!";
LOG(LogError) << e.what();
return;
}
//load the metadata
file->Metadata().Deserialize(fileNode, relativeTo.generic_string());
fs::path relativeTo = system->getStartPath();
fs::path path;
for (const auto& fileNode : gameList.get_child("gameList"))
{
ItemType type;
if (fileNode.first == "game") type = ItemType::Game;
else if (fileNode.first == "folder") type = ItemType::Folder;
else continue; // Unknown node
const MetadataDescriptor::Tree& children = fileNode.second;
path = resolvePath(children.get("path", ""), relativeTo, false);
if(!trustGamelist && !boost::filesystem::exists(path))
{
LOG(LogWarning) << "File \"" << path << "\" does not exist! Ignoring.";
continue;
}
FileData* file = findOrCreateFile(system, path, type, trustGamelist, doppelgangerWatcher);
if(!file)
{
LOG(LogError) << "Error finding/creating FileData for \"" << path << "\", skipping.";
continue;
}
//load the metadata
file->Metadata().Deserialize(fileNode, relativeTo.generic_string());
}
}
catch(std::exception& ex)
{
LOG(LogError) << "System \"" << system->getName() << "\" has raised an error while reading its gamelist.xml!";
LOG(LogError) << "Exception: " << ex.what();
}
}
......
......@@ -45,42 +45,19 @@ void NetPlayThread::Stop()
void NetPlayThread::run()
{
boost::this_thread::sleep(boost::posix_time::seconds(5));
LOG(LogInfo) << "NetPlayThread started";
int popupDuration = Settings::getInstance()->getInt("NetplayPopupTime");
if (popupDuration != 0)
try
{
std::vector<std::pair<std::string, std::string>> oldGames;
std::string lobby = RecalboxConf::getInstance()->get("global.netplay.lobby");
boost::this_thread::sleep(boost::posix_time::seconds(5));
auto json_req = RecalboxSystem::getInstance()->execute("curl -s --connect-timeout 3 -m 3 " + lobby);
if (json_req.second == 0)
{
json::ptree root;
std::stringstream ss;
ss << json_req.first;
try
{
json::read_json(ss, root);
}
catch (const boost::property_tree::json_parser_error& e1)
{
LOG(LogInfo) << "NetPlayThread error";
}
LOG(LogInfo) << "NetPlayThread started";
for (json::ptree::value_type& array_element : root)
{
std::string player = array_element.second.get<std::string>("fields.username");
std::string game = array_element.second.get<std::string>("fields.game_name");
oldGames.push_back(std::make_pair(player, game));
}
}
while (mRunning)
int popupDuration = Settings::getInstance()->getInt("NetplayPopupTime");
if (popupDuration != 0)
{
json_req = RecalboxSystem::getInstance()->execute("curl -s --connect-timeout 3 -m 3 " + mLobby);
std::vector<std::pair<std::string, std::string>> oldGames;
std::string lobby = RecalboxConf::getInstance()->get("global.netplay.lobby");
auto json_req = RecalboxSystem::getInstance()->execute("curl -s --connect-timeout 3 -m 3 " + lobby);
if (json_req.second == 0)
{
json::ptree root;
......@@ -95,48 +72,77 @@ void NetPlayThread::run()
LOG(LogInfo) << "NetPlayThread error";
}
std::vector<std::pair<std::string,
std::string>> newGames;
for (json::ptree::value_type& array_element : root)
{
std::string player = array_element.second.get<std::string>("fields.username");
std::string game = array_element.second.get<std::string>("fields.game_name");
newGames.push_back(std::make_pair(player, game));
oldGames.push_back(std::make_pair(player, game));
}
for (auto tmp : newGames)
}
while (mRunning)
{
json_req = RecalboxSystem::getInstance()->execute("curl -s --connect-timeout 3 -m 3 " + mLobby);
if (json_req.second == 0)
{
std::vector<std::pair<std::string,
std::string>>::const_iterator it;
it = std::find(oldGames.begin(), oldGames.end(), tmp);
if (it == oldGames.end())
json::ptree root;
std::stringstream ss;
ss << json_req.first;
try
{
if (tmp.first.find("RECALBOX") != std::string::npos)
{
// Create popup text
mLastPopupText = _("A Recalbox friend has started a Netplay game!")
+ "\n " + _("Player") + ": " + tmp.first;
+ "\n " + _("Game") + ": " + tmp.second;
// Create event
SDL_Event event;
event.user.type = (unsigned int)mEvent;
json::read_json(ss, root);
}
catch (const boost::property_tree::json_parser_error& e1)
{
LOG(LogInfo) << "NetPlayThread error";
}
// Push event to the main thread so that all GUI operations are safely run in the main thread.
// SDL_PushEvent is synchronized & thread-safe
SDL_PushEvent(&event);
std::vector<std::pair<std::string, std::string>> newGames;
break;
for (json::ptree::value_type& array_element : root)
{
std::string player = array_element.second.get<std::string>("fields.username");
std::string game = array_element.second.get<std::string>("fields.game_name");
newGames.push_back(std::make_pair(player, game));
}
for (auto tmp : newGames)
{
std::vector<std::pair<std::string, std::string>>::const_iterator it;
it = std::find(oldGames.begin(), oldGames.end(), tmp);
if (it == oldGames.end())
{
if (tmp.first.find("RECALBOX") != std::string::npos)
{
// Create popup text
mLastPopupText = _("A Recalbox friend has started a Netplay game!") + "\n " + _("Player") + ": " +
tmp.first;
+"\n " + _("Game") + ": " + tmp.second;
// Create event
SDL_Event event;
event.user.type = (unsigned int) mEvent;
// Push event to the main thread so that all GUI operations are safely run in the main thread.
// SDL_PushEvent is synchronized & thread-safe
SDL_PushEvent(&event);
break;
}
}
}
oldGames = newGames;
}
oldGames = newGames;
}
for(int i=30; --i >= 0 && mRunning;)
boost::this_thread::sleep(boost::posix_time::seconds(1));
for (int i = 30; --i >= 0 && mRunning;)
boost::this_thread::sleep(boost::posix_time::seconds(1));
}
}
}
catch(std::exception& ex)
{
LOG(LogError) << "Main thread crashed.";
LOG(LogError) << "Exception: " << ex.what();
}
}
std::string NetPlayThread::GetLastPopupText()
......
......@@ -5,6 +5,7 @@
* Created on 6 février 2015, 11:40
*/
#include <Log.h>
#include "NetworkThread.h"
#include "recalbox/RecalboxSystem.h"
#include "recalbox/RecalboxUpgrade.h"
......@@ -26,37 +27,45 @@ NetworkThread::~NetworkThread()
void NetworkThread::run()
{
if (RecalboxConf::getInstance()->get("updates.enabled") != "1")
mRunning = false;
int waitForSeconds = 15;
while (mRunning)
try
{
boost::this_thread::sleep(boost::posix_time::seconds(waitForSeconds));
waitForSeconds = 3600;
if (RecalboxConf::getInstance()->get("updates.enabled") != "1")
mRunning = false;
if (RecalboxUpgrade::getInstance()->canUpdate())
int waitForSeconds = 15;
while (mRunning)
{
std::string changelog = RecalboxUpgrade::getInstance()->getUpdateChangelog();
boost::this_thread::sleep(boost::posix_time::seconds(waitForSeconds));
waitForSeconds = 3600;
while (mWindow->isShowingPopup())
if (RecalboxUpgrade::getInstance()->canUpdate())
{
boost::this_thread::sleep(boost::posix_time::seconds(5));
}
std::string changelog = RecalboxUpgrade::getInstance()->getUpdateChangelog();
if (changelog != "")
{
std::string message = changelog;
std::string updateVersion = RecalboxUpgrade::getInstance()->getUpdateVersion();
mWindow->displayScrollMessage(_("AN UPDATE IS AVAILABLE FOR YOUR RECALBOX"),
_("UPDATE VERSION:") + " " + updateVersion + "\n" +
_("UPDATE CHANGELOG:") + "\n" + message);
}
else
{
mWindow->displayMessage(_("AN UPDATE IS AVAILABLE FOR YOUR RECALBOX"));
while (mWindow->isShowingPopup())
{
boost::this_thread::sleep(boost::posix_time::seconds(5));
}
if (changelog != "")
{
std::string message = changelog;
std::string updateVersion = RecalboxUpgrade::getInstance()->getUpdateVersion();
mWindow->displayScrollMessage(_("AN UPDATE IS AVAILABLE FOR YOUR RECALBOX"),
_("UPDATE VERSION:") + " " + updateVersion + "\n" + _("UPDATE CHANGELOG:") +
"\n" + message);
}
else
{
mWindow->displayMessage(_("AN UPDATE IS AVAILABLE FOR YOUR RECALBOX"));
}
}
}
}
catch(std::exception& ex)
{
LOG(LogError) << "Main thread crashed.";
LOG(LogError) << "Exception: " << ex.what();
}
}
......@@ -56,7 +56,7 @@ SystemData* SystemData::CreateFavoriteSystem(const std::string& name, const std:
for (auto system : systems)
{
FileData::List favs = system->getFavorites();
if (favs.size() > 0)
if (!favs.empty())
{
LOG(LogWarning) << " Get " << favs.size() << " favorites for " << system->getName() << "!";
for (auto favorite : favs)
......@@ -193,8 +193,8 @@ void SystemData::launchGame(Window* window, FileData* game, const std::string& n
else if (netplay == "host")
{
std::string hash = game->Metadata().RomCrc32AsString();
std::string hashcmd = "";
if (hash != "")
std::string hashcmd;
if (!hash.empty())
{
hashcmd = " -hash " + hash;
}
......@@ -231,7 +231,15 @@ void SystemData::launchGame(Window* window, FileData* game, const std::string& n
void SystemData::populateFolder(FolderData *folder, FileData::StringMap& doppelgangerWatcher)
{
folder->populateRecursiveFolder(mSearchExtensions, this, doppelgangerWatcher);
try
{
folder->populateRecursiveFolder(mSearchExtensions, this, doppelgangerWatcher);
}
catch(std::exception& ex)
{
LOG(LogError) << "Reading folder \"" << folder->getPath().generic_string() << "\" has raised an error!";
LOG(LogError) << "Exception: " << ex.what();
}
}
std::vector<std::string> readList(const std::string &str, const char *delims = " \t\r\n,")
......@@ -254,70 +262,78 @@ std::vector<std::string> readList(const std::string &str, const char *delims = "
SystemData *createSystem(const SystemData::Tree &system)
{
std::string name, fullname, path, cmd, themeFolder;
try
{
name = system.get("name", "");
fullname = system.get("fullname", "");
path = system.get("path", "");
name = system.get("name", "");
fullname = system.get("fullname", "");
path = system.get("path", "");
// convert extensions list from a string into a vector of strings
std::string extensions = system.get("extension", "");
// convert extensions list from a string into a vector of strings
std::string extensions = system.get("extension", "");
cmd = system.get("command", "");
cmd = system.get("command", "");
// platform id list
const std::string platformList = system.get("platform", "");
std::vector<std::string> platformStrs = readList(platformList);
std::vector<PlatformIds::PlatformId> platformIds;
for (const auto &it : platformStrs)
{
const char *str = it.c_str();
PlatformIds::PlatformId platformId = PlatformIds::getPlatformId(str);
// platform id list
const std::string platformList = system.get("platform", "");
std::vector<std::string> platformStrs = readList(platformList);
std::vector<PlatformIds::PlatformId> platformIds;
for (const auto &it : platformStrs)
{
const char *str = it.c_str();
PlatformIds::PlatformId platformId = PlatformIds::getPlatformId(str);
if (platformId == PlatformIds::PLATFORM_IGNORE)
{
// when platform is ignore, do not allow other platforms
platformIds.clear();
platformIds.push_back(platformId);
break;
}
if (platformId == PlatformIds::PLATFORM_IGNORE)
{
// when platform is ignore, do not allow other platforms
platformIds.clear();
platformIds.push_back(platformId);
break;
// if there appears to be an actual platform ID supplied but it didn't match the list, warn
if (str != nullptr && str[0] != '\0' && platformId == PlatformIds::PLATFORM_UNKNOWN)
LOG(LogWarning) << " Unknown platform for system \"" << name << "\" (platform \"" << str << "\" from list \"" << platformList << "\")";
else if (platformId != PlatformIds::PLATFORM_UNKNOWN)
platformIds.push_back(platformId);
}
// if there appears to be an actual platform ID supplied but it didn't match the list, warn
if (str != nullptr && str[0] != '\0' && platformId == PlatformIds::PLATFORM_UNKNOWN)
LOG(LogWarning) << " Unknown platform for system \"" << name << "\" (platform \"" << str << "\" from list \"" << platformList << "\")";
else if (platformId != PlatformIds::PLATFORM_UNKNOWN)
platformIds.push_back(platformId);
}
// theme folder
themeFolder = system.get("theme", "");
// theme folder
themeFolder = system.get("theme", "");
//validate
if (name.empty() || path.empty() || extensions.empty() || cmd.empty())
{
LOG(LogError) << "System \"" << name << "\" is missing name, path, extension, or command!";
return nullptr;
}
//validate
if (name.empty() || path.empty() || extensions.empty() || cmd.empty())
{
LOG(LogError) << "System \"" << name << "\" is missing name, path, extension, or command!";
return nullptr;
}
//convert path to generic directory seperators
boost::filesystem::path genericPath(path);
path = genericPath.generic_string();
//convert path to generic directory seperators
boost::filesystem::path genericPath(path);
path = genericPath.generic_string();
SystemData* newSys = SystemData::CreateRegularSystem(name, fullname,
path, extensions,
cmd, platformIds,
themeFolder,
system.get_child("emulators"));
if (newSys->getRootFolder()->countAll(false) == 0)
{
LOG(LogWarning) << "System \"" << name << "\" has no games! Ignoring it.";
delete newSys;
return nullptr;
SystemData* newSys = SystemData::CreateRegularSystem(name, fullname,
path, extensions,
cmd, platformIds,
themeFolder,
system.get_child("emulators"));
if (newSys->getRootFolder()->countAll(false) == 0)
{
LOG(LogWarning) << "System \"" << name << "\" has no games! Ignoring it.";
delete newSys;
return nullptr;
}
else
{
LOG(LogWarning) << "Adding \"" << name << "\" in system list.";
return newSys;
}
}
else
catch(std::exception& ex)
{
LOG(LogWarning) << "Adding \"" << name << "\" in system list.";
return newSys;
LOG(LogError) << "System \"" << fullname << "\" has raised an error. Ignored.";
LOG(LogError) << "Exception: " << ex.what();
}
return nullptr;
}
bool SystemData::loadSystemNodes(XmlNodeCollisionMap &collisionMap, XmlNodeList &nodeStore, const Tree &document)
......@@ -600,26 +616,22 @@ std::string SystemData::getThemePath() const
// first, check game folder
fs::path localThemePath = mRootFolder.getPath() / "theme.xml";
if (fs::exists(localThemePath))
return localThemePath.generic_string();
if (fs::exists(localThemePath)) return localThemePath.generic_string();
// not in game folder, try system theme in theme sets
localThemePath = ThemeData::getThemeFromCurrentSet(mThemeFolder);
if (fs::exists(localThemePath))
return localThemePath.generic_string();
if (fs::exists(localThemePath)) return localThemePath.generic_string();
// not system theme, try default system theme in theme set
localThemePath = localThemePath.parent_path().parent_path() / "theme.xml";
if (fs::exists(localThemePath))
return localThemePath.generic_string();
if (fs::exists(localThemePath)) return localThemePath.generic_string();
//none of the above, try default
localThemePath = localThemePath.parent_path() / "default/theme.xml";
if (fs::exists(localThemePath))
return localThemePath.generic_string();
if (fs::exists(localThemePath)) return localThemePath.generic_string();
// No luck...
return "";
......@@ -656,7 +668,7 @@ std::map<std::string, std::vector<std::string> *> *SystemData::getEmulators()
std::vector<std::string> SystemData::getCores(const std::string &emulatorName)
{
std::vector<std::string> list;
for (auto emulator : mEmulators)
for (auto& emulator : mEmulators)
{
if (emulatorName == emulator.first)
{
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment