diff --git a/server/src/Group.cpp b/server/src/Group.cpp index 7815d82..771b7f1 100644 --- a/server/src/Group.cpp +++ b/server/src/Group.cpp @@ -92,6 +92,7 @@ GroupManager::GroupManager(const shared_ptr &server, sql::SqlMana GroupManager::~GroupManager() {} bool GroupManager::loadGroupFormDatabase(GroupId id) { + std::lock_guard glock{this->group_lock}; if(id == 0){ this->groups.clear(); @@ -115,8 +116,13 @@ bool GroupManager::loadGroupFormDatabase(GroupId id) { std::vector> GroupManager::availableGroups(bool root) { std::vector> response; - for(const auto& group : this->groups) - response.push_back(group); + + { + std::lock_guard glock{this->group_lock}; + for(const auto& group : this->groups) + response.push_back(group); + } + if(root && this->root){ auto elm = this->root->availableGroups(); for(const auto& e : elm) @@ -127,9 +133,14 @@ std::vector> GroupManager::availableGroups(bool root) { std::vector> GroupManager::availableServerGroups(bool root){ std::vector> response; - for(const auto& group : this->groups) - if(group->target() == GroupTarget::GROUPTARGET_SERVER) - response.push_back(group); + + { + std::lock_guard glock{this->group_lock}; + for(const auto& group : this->groups) + if(group->target() == GroupTarget::GROUPTARGET_SERVER) + response.push_back(group); + } + if(root && this->root){ auto elm = this->root->availableServerGroups(); for(const auto& e : elm) @@ -140,9 +151,12 @@ std::vector> GroupManager::availableServerGroups(bool roo std::vector> GroupManager::availableChannelGroups(bool root) { std::vector> response; - for(const auto& group : this->groups) - if(group->target() == GroupTarget::GROUPTARGET_CHANNEL) - response.push_back(group); + { + std::lock_guard glock{this->group_lock}; + for(const auto& group : this->groups) + if(group->target() == GroupTarget::GROUPTARGET_CHANNEL) + response.push_back(group); + } if(root && this->root){ auto elm = this->root->availableChannelGroups(true); for(const auto& e : elm) @@ -237,6 +251,7 @@ void GroupManager::handleChannelDeleted(const ChannelId& channel_id) { } bool GroupManager::isLocalGroup(std::shared_ptr gr) { + std::lock_guard glock{this->group_lock}; return std::find(this->groups.begin(), this->groups.end(), gr) != this->groups.end(); } @@ -252,9 +267,12 @@ std::shared_ptr GroupManager::defaultGroup(GroupTarget type, bool enforce auto group = this->findGroupLocal(id); if(group || enforce_property) return group; - for(auto elm : this->groups) - if(elm->target() == type) - return elm; + { + std::lock_guard glock{this->group_lock}; + for(auto elm : this->groups) + if(elm->target() == type) + return elm; + } return nullptr; //Worst case! } @@ -266,6 +284,7 @@ std::shared_ptr GroupManager::findGroup(GroupId groupId) { } std::shared_ptr GroupManager::findGroupLocal(GroupId groupId) { + std::lock_guard glock{this->group_lock}; for(const auto& elm : this->groups) if(elm->groupId() == groupId) return elm; return nullptr; @@ -273,8 +292,11 @@ std::shared_ptr GroupManager::findGroupLocal(GroupId groupId) { std::vector> GroupManager::findGroup(GroupTarget target, std::string name) { vector> res; - for(const auto &elm : this->groups) - if(elm->name() == name && elm->target() == target) res.push_back(elm); + { + std::lock_guard glock{this->group_lock}; + for(const auto &elm : this->groups) + if(elm->name() == name && elm->target() == target) res.push_back(elm); + } if(this->root) { auto r = root->findGroup(target, name); for(const auto &e : r) res.push_back(e); @@ -305,6 +327,8 @@ std::shared_ptr GroupManager::createGroup(GroupTarget target, GroupType t std::shared_ptr group = std::make_shared(this, target, type, groupId); group->properties()[property::GROUP_NAME] = name; group->setPermissionManager(serverInstance->databaseHelper()->loadGroupPermissions(this->server.lock(), group->groupId())); + + std::lock_guard glock{this->group_lock}; this->groups.push_back(group); return group; } @@ -394,7 +418,10 @@ bool GroupManager::deleteGroup(std::shared_ptr group) { return false; } - this->groups.erase(std::find(this->groups.begin(), this->groups.end(), group)); + { + std::lock_guard glock{this->group_lock}; + this->groups.erase(std::find(this->groups.begin(), this->groups.end(), group)); + } /* erase the group out of our cache */ { diff --git a/server/src/Group.h b/server/src/Group.h index 4a9323d..eab8861 100644 --- a/server/src/Group.h +++ b/server/src/Group.h @@ -224,7 +224,10 @@ namespace ts { ServerId getServerId(); sql::SqlManager* sql; + + std::mutex group_lock{}; std::vector> groups; + threads::Mutex cacheLock; std::vector> cachedClients; diff --git a/server/src/VirtualServer.cpp b/server/src/VirtualServer.cpp index 6c98452..d05edd9 100644 --- a/server/src/VirtualServer.cpp +++ b/server/src/VirtualServer.cpp @@ -758,9 +758,9 @@ bool VirtualServer::notifyServerEdited(std::shared_ptr invoker, } bool VirtualServer::notifyClientPropertyUpdates(std::shared_ptr client, const deque& keys, bool selfNotify) { - if(keys.empty()) return false; + if(keys.empty() || !client) return false; this->forEachClient([&](const shared_ptr& cl) { - shared_lock client_channel_lock(client->channel_lock); + shared_lock client_channel_lock(cl->channel_lock); if(cl->isClientVisible(client, false) || (cl == client && selfNotify)) cl->notifyClientUpdated(client, keys, false); }); diff --git a/shared b/shared index f404d5e..246e57e 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit f404d5e1fa5ed1cfbe3ef9a97c0e81c1fba943ff +Subproject commit 246e57e69d61d25d92e76c2af0368eac18536ac1