X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fcull_list.cpp;h=00c9161994385789f354aa5f9d4904eae6e9685a;hb=84a19a9ab6129deb71cdc24b216b74dd8eb80978;hp=f1dd5b4d99e83070b3dda074dbba6ea83af9ccff;hpb=dc6720574e9a07327c3924e459029426effb450e;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/cull_list.cpp b/src/cull_list.cpp index f1dd5b4d9..00c916199 100644 --- a/src/cull_list.cpp +++ b/src/cull_list.cpp @@ -18,17 +18,7 @@ using namespace std; #include "inspircd_config.h" #include "inspircd.h" -#include "inspircd_io.h" -#include -#include -#include -#include #include -#ifdef GCC3 -#include -#else -#include -#endif #include #include #include @@ -50,58 +40,101 @@ using namespace std; #include "cull_list.h" extern InspIRCd* ServerInstance; +extern user_hash clientlist; -CullItem::CullItem(userrec* u, std::string r) +/* + * In current implementation of CullList, this isn't used. It did odd things with a lot of sockets. + */ +bool CullList::IsValid(userrec* user) +{ + time_t esignon = 0; + std::map::iterator es = exempt.find(user); + if (es != exempt.end()) + esignon = es->second; + + for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++) + { + /* + * BUGFIX + * + * Because there is an undetermined period of time between a user existing, + * and this function being called, we have to check for the following condition: + * + * Between CullList::AddItem(u) being called, and CullList::IsValid(u) being called, + * the user with the pointer u has quit, but only to be REPLACED WITH A NEW USER WHO + * BECAUSE OF ALLOCATION RULES, HAS THE SAME MEMORY ADDRESS! To prevent this, we + * cross reference each pointer to the user's signon time, and if the signon times + * do not match, we return false here to indicate this user is NOT valid as it + * seems to differ from the pointer snapshot we got a few seconds earlier. Should + * prevent a few random crashes during netsplits. + */ + if (user == u->second) + return (u->second->signon == esignon); + } + return false; +} + +CullItem::CullItem(userrec* u, std::string &r) +{ + this->user = u; + this->reason = r; +} + +CullItem::CullItem(userrec* u, const char* r) +{ + this->user = u; + this->reason = r; +} + +CullItem::~CullItem() { - this->user = u; - this->reason = r; } userrec* CullItem::GetUser() { - return this->user; + return this->user; } -std::string CullItem::GetReason() +std::string& CullItem::GetReason() { - return this->reason; + return this->reason; } CullList::CullList() { list.clear(); - exempt.clear(); + exempt.clear(); +} + +void CullList::AddItem(userrec* user, std::string &reason) +{ + if (exempt.find(user) == exempt.end()) + { + CullItem item(user,reason); + list.push_back(item); + exempt[user] = user->signon; + } } -void CullList::AddItem(userrec* user, std::string reason) +void CullList::AddItem(userrec* user, const char* reason) { if (exempt.find(user) == exempt.end()) { - CullItem item(user,reason); - list.push_back(item); - exempt[user] = 1; + CullItem item(user,reason); + list.push_back(item); + exempt[user] = user->signon; } } int CullList::Apply() { - int n = 0; - while (list.size()) - { + int n = 0; + while (list.size()) + { std::vector::iterator a = list.begin(); - userrec* u = a->GetUser(); - kill_link(u,a->GetReason().c_str()); + + kill_link(a->GetUser(), a->GetReason().c_str()); list.erase(list.begin()); - /* So that huge numbers of quits dont block, - * we yield back to our mainloop every 15 - * iterations. - * The DoOneIteration call basically acts - * like a software threading mechanism. - */ - if ((n++ % 15) == 0) - { - ServerInstance->DoOneIteration(false); - } - } - return n; + } + return n; }