mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-05 15:30:00 +01:00
BugFix: interrupting recursive session loading
Prevent crash on recursive (infinite) loading of session file (containing itself).
This commit is contained in:
@@ -948,7 +948,7 @@ void Mixer::load(const std::string& filename)
|
||||
if (sessionLoaders_.empty()) {
|
||||
// Start async thread for loading the session
|
||||
// Will be obtained in the future in update()
|
||||
sessionLoaders_.emplace_back( std::async(std::launch::async, Session::load, filename) );
|
||||
sessionLoaders_.emplace_back( std::async(std::launch::async, Session::load, filename, 0) );
|
||||
}
|
||||
#else
|
||||
set( Session::load(filename) );
|
||||
@@ -986,7 +986,7 @@ void Mixer::import(const std::string& filename)
|
||||
if (sessionImporters_.empty()) {
|
||||
// Start async thread for loading the session
|
||||
// Will be obtained in the future in update()
|
||||
sessionImporters_.emplace_back( std::async(std::launch::async, Session::load, filename) );
|
||||
sessionImporters_.emplace_back( std::async(std::launch::async, Session::load, filename, 0) );
|
||||
}
|
||||
#else
|
||||
merge( Session::load(filename) );
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "SearchVisitor.h"
|
||||
|
||||
#include "Scene.h"
|
||||
#include "MediaSource.h"
|
||||
#include "Session.h"
|
||||
#include "SessionSource.h"
|
||||
|
||||
SearchVisitor::SearchVisitor(Node *node) : Visitor(), node_(node), found_(false)
|
||||
{
|
||||
@@ -42,12 +47,11 @@ void SearchVisitor::visit(Scene &n)
|
||||
|
||||
|
||||
|
||||
SearchFileVisitor::SearchFileVisitor(std::string filename) : Visitor(), filename_(filename), found_(false)
|
||||
SearchFileVisitor::SearchFileVisitor() : Visitor()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SearchFileVisitor::visit(Node &n)
|
||||
{
|
||||
|
||||
@@ -55,13 +59,8 @@ void SearchFileVisitor::visit(Node &n)
|
||||
|
||||
void SearchFileVisitor::visit(Group &n)
|
||||
{
|
||||
if (found_)
|
||||
return;
|
||||
|
||||
for (NodeSet::iterator node = n.begin(); node != n.end(); node++) {
|
||||
(*node)->accept(*this);
|
||||
if (found_)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,10 +80,29 @@ void SearchFileVisitor::visit(Scene &n)
|
||||
|
||||
void SearchFileVisitor::visit (MediaSource& s)
|
||||
{
|
||||
|
||||
filenames_.push_back( s.path() );
|
||||
}
|
||||
|
||||
void SearchFileVisitor::visit (SessionFileSource& s)
|
||||
{
|
||||
|
||||
filenames_.push_back( s.path() );
|
||||
}
|
||||
|
||||
std::list<std::string> SearchFileVisitor::parse (Session *se)
|
||||
{
|
||||
SearchFileVisitor sv;
|
||||
|
||||
for (auto iter = se->begin(); iter != se->end(); iter++){
|
||||
(*iter)->accept(sv);
|
||||
}
|
||||
|
||||
return sv.filenames();
|
||||
}
|
||||
|
||||
bool SearchFileVisitor::find (Session *se, std::string path)
|
||||
{
|
||||
std::list<std::string> filenames = parse (se);
|
||||
return std::find(filenames.begin(), filenames.end(), path) != filenames.end();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#ifndef SEARCHVISITOR_H
|
||||
#define SEARCHVISITOR_H
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include "Visitor.h"
|
||||
|
||||
class Session;
|
||||
|
||||
class SearchVisitor: public Visitor
|
||||
{
|
||||
Node *node_;
|
||||
@@ -15,33 +18,35 @@ public:
|
||||
inline Node *node() const { return found_ ? node_ : nullptr; }
|
||||
|
||||
// Elements of Scene
|
||||
void visit(Scene& n) override;
|
||||
void visit(Node& n) override;
|
||||
void visit(Primitive&) override {}
|
||||
void visit(Group& n) override;
|
||||
void visit(Switch& n) override;
|
||||
void visit (Scene& n) override;
|
||||
void visit (Node& n) override;
|
||||
void visit (Primitive&) override {}
|
||||
void visit (Group& n) override;
|
||||
void visit (Switch& n) override;
|
||||
|
||||
};
|
||||
|
||||
class SearchFileVisitor: public Visitor
|
||||
{
|
||||
std::string filename_;
|
||||
bool found_;
|
||||
std::list<std::string> filenames_;
|
||||
|
||||
public:
|
||||
SearchFileVisitor(std::string filename);
|
||||
inline bool found() const { return found_; }
|
||||
SearchFileVisitor();
|
||||
inline std::list<std::string> filenames() const { return filenames_; }
|
||||
|
||||
// Elements of Scene
|
||||
void visit(Scene& n) override;
|
||||
void visit(Node& n) override;
|
||||
void visit(Primitive&) override {}
|
||||
void visit(Group& n) override;
|
||||
void visit(Switch& n) override;
|
||||
void visit (Scene& n) override;
|
||||
void visit (Node& n) override;
|
||||
void visit (Primitive&) override {}
|
||||
void visit (Group& n) override;
|
||||
void visit (Switch& n) override;
|
||||
|
||||
// Sources
|
||||
void visit (MediaSource& s) override;
|
||||
void visit (SessionFileSource& s) override;
|
||||
|
||||
static std::list<std::string> parse (Session *se);
|
||||
static bool find (Session *se, std::string path);
|
||||
};
|
||||
|
||||
#endif // SEARCHVISITOR_H
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "Settings.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "Session.h"
|
||||
#include "GarbageVisitor.h"
|
||||
#include "FrameGrabber.h"
|
||||
#include "SessionCreator.h"
|
||||
#include "SessionSource.h"
|
||||
@@ -323,9 +322,9 @@ void Session::unlock()
|
||||
}
|
||||
|
||||
|
||||
Session *Session::load(const std::string& filename)
|
||||
Session *Session::load(const std::string& filename, uint recursion)
|
||||
{
|
||||
SessionCreator creator;
|
||||
SessionCreator creator(recursion);
|
||||
creator.load(filename);
|
||||
|
||||
return creator.session();
|
||||
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
Session();
|
||||
~Session();
|
||||
|
||||
static Session *load(const std::string& filename);
|
||||
static Session *load(const std::string& filename, uint recursion = 0);
|
||||
|
||||
// add given source into the session
|
||||
SourceList::iterator addSource (Source *s);
|
||||
|
||||
@@ -52,7 +52,7 @@ std::string SessionCreator::info(const std::string& filename)
|
||||
return ret;
|
||||
}
|
||||
|
||||
SessionCreator::SessionCreator(): SessionLoader(nullptr)
|
||||
SessionCreator::SessionCreator(uint recursion): SessionLoader(nullptr, recursion)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -108,7 +108,7 @@ void SessionCreator::loadConfig(XMLElement *viewsNode)
|
||||
}
|
||||
}
|
||||
|
||||
SessionLoader::SessionLoader(Session *session): Visitor(), session_(session)
|
||||
SessionLoader::SessionLoader(Session *session, uint recursion): Visitor(), session_(session), recursion_(recursion)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -117,6 +117,11 @@ void SessionLoader::load(XMLElement *sessionNode)
|
||||
{
|
||||
sources_id_.clear();
|
||||
|
||||
if (recursion_ > MAX_SESSION_LEVEL) {
|
||||
Log::Warning("Recursive or imbricated sessions detected! Interrupting loading after %d iterations.\n", MAX_SESSION_LEVEL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sessionNode != nullptr && session_ != nullptr) {
|
||||
|
||||
XMLElement* sourceNode = sessionNode->FirstChildElement("Source");
|
||||
@@ -534,11 +539,11 @@ void SessionLoader::visit (SessionFileSource& s)
|
||||
XMLElement* pathNode = xmlCurrent_->FirstChildElement("path");
|
||||
if (pathNode) {
|
||||
std::string path = std::string ( pathNode->GetText() );
|
||||
|
||||
// load only new files
|
||||
if ( path != s.path() )
|
||||
s.load(path);
|
||||
s.load(path, recursion_ + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SessionLoader::visit (SessionGroupSource& s)
|
||||
@@ -550,10 +555,9 @@ void SessionLoader::visit (SessionGroupSource& s)
|
||||
XMLElement* sessionGroupNode = xmlCurrent_->FirstChildElement("Session");
|
||||
if (sessionGroupNode) {
|
||||
// load session inside group
|
||||
SessionLoader grouploader( s.session() );
|
||||
SessionLoader grouploader( s.session(), recursion_ + 1 );
|
||||
grouploader.load( sessionGroupNode );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SessionLoader::visit (RenderSource& s)
|
||||
|
||||
@@ -13,7 +13,7 @@ class SessionLoader : public Visitor {
|
||||
|
||||
public:
|
||||
|
||||
SessionLoader(Session *session);
|
||||
SessionLoader(Session *session, uint recursion = 0);
|
||||
inline Session *session() const { return session_; }
|
||||
|
||||
void load(tinyxml2::XMLElement *sessionNode);
|
||||
@@ -58,6 +58,7 @@ protected:
|
||||
tinyxml2::XMLElement *xmlCurrent_;
|
||||
Session *session_;
|
||||
std::list<uint64_t> sources_id_;
|
||||
uint recursion_;
|
||||
|
||||
static void XMLToNode(tinyxml2::XMLElement *xml, Node &n);
|
||||
};
|
||||
@@ -69,7 +70,7 @@ class SessionCreator : public SessionLoader {
|
||||
void loadConfig(tinyxml2::XMLElement *viewsNode);
|
||||
|
||||
public:
|
||||
SessionCreator();
|
||||
SessionCreator(uint recursion = 0);
|
||||
|
||||
void load(const std::string& filename);
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ SessionFileSource::SessionFileSource() : SessionSource(), path_("")
|
||||
wait_for_sources_ = false;
|
||||
}
|
||||
|
||||
void SessionFileSource::load(const std::string &p)
|
||||
void SessionFileSource::load(const std::string &p, uint recursion)
|
||||
{
|
||||
path_ = p;
|
||||
|
||||
@@ -142,10 +142,11 @@ void SessionFileSource::load(const std::string &p)
|
||||
if ( path_.empty() ) {
|
||||
// empty session
|
||||
session_ = new Session;
|
||||
Log::Warning("Empty Session filename provided.");
|
||||
}
|
||||
else {
|
||||
// launch a thread to load the session file
|
||||
sessionLoader_ = std::async(std::launch::async, Session::load, path_);
|
||||
sessionLoader_ = std::async(std::launch::async, Session::load, path_, recursion);
|
||||
Log::Notify("Opening %s", p.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
void accept (Visitor& v) override;
|
||||
|
||||
// SessionFile Source specific interface
|
||||
void load(const std::string &p = "");
|
||||
void load(const std::string &p = "", uint recursion = 0);
|
||||
|
||||
inline std::string path() const { return path_; }
|
||||
glm::ivec2 icon() const override { return glm::ivec2(2, 16); }
|
||||
|
||||
@@ -433,9 +433,10 @@ void SessionVisitor::visit (SessionGroupSource& s)
|
||||
XMLElement *rootgroup = xmlDoc_->NewElement("Session");
|
||||
xmlCurrent_->InsertEndChild(rootgroup);
|
||||
|
||||
for (auto iter = se->begin(); iter != se->end(); iter++){
|
||||
setRoot(rootgroup);
|
||||
for (auto iter = se->begin(); iter != se->end(); iter++, setRoot(rootgroup) )
|
||||
(*iter)->accept(*this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user