summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpeavey <peavey@e03df62e-2008-0410-955e-edbf42e46eb7>2007-01-02 20:22:23 +0000
committerpeavey <peavey@e03df62e-2008-0410-955e-edbf42e46eb7>2007-01-02 20:22:23 +0000
commit8bd2f571e9950a61653fce5ccfddace3fd48ed15 (patch)
treec2161d8a119a39bf2f3af82afe766367e493f2ad
parent3863f71f8b0775e1987e8aacdfb9e5014def9279 (diff)
Fix for crash in desync of whowas lists on rehash. Also less mem leakage on adding to whowas.
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@6217 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--src/users.cpp99
1 files changed, 64 insertions, 35 deletions
diff --git a/src/users.cpp b/src/users.cpp
index f918baefa..ac9fbd109 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -913,49 +913,61 @@ namespace irc
int maxgroups = ServerInstance->Config->WhoWasMaxGroups;
int maxkeep = ServerInstance->Config->WhoWasMaxKeep;
- int groupcount = ServerInstance->whowas.size();
- /* iterate whowas_fifo oldest first */
- whowas_users_fifo::iterator iter, safeiter;
- for (iter = ServerInstance->whowas_fifo.begin(); iter != ServerInstance->whowas_fifo.end(); iter++)
+ /* first cut the list to new size (maxgroups) and also prune entries that are timed out. */
+ whowas_users::iterator iter;
+ int fifosize;
+ while ((fifosize = (int)ServerInstance->whowas_fifo.size()) > 0)
{
- /** prune all groups that has expired due to new maxkeep time and
- * also any group number higher than new maxgroups. The oldest are
- * removed first due to iteration over whowas_fifo
- */
- if (groupcount > maxgroups || iter->first < t - maxkeep)
+ if (fifosize > maxgroups || ServerInstance->whowas_fifo[0].first < t - maxkeep)
{
- whowas_set* n = (whowas_set*)ServerInstance->whowas.find(iter->second)->second;
+ iter = ServerInstance->whowas.find(ServerInstance->whowas_fifo[0].second);
+ /* hopefully redundant integrity check, but added while debugging r6216 */
+ if (iter == ServerInstance->whowas.end())
+ {
+ /* this should never happen, if it does maps are corrupt */
+ ServerInstance->Log(DEBUG, "Whowas maps got corrupted! (1)");
+ return;
+ }
+ whowas_set* n = (whowas_set*)iter->second;
if (n->size())
{
while (n->begin() != n->end())
{
WhoWasGroup *a = *(n->begin());
DELETE(a);
- n->erase(n->begin());
+ n->pop_front();
}
}
- ServerInstance->whowas.erase(iter->second);
- /* use a safe iter copy for erase and set the orig iter old valid ref by decrementing it */
- safeiter = iter;
- --iter;
- ServerInstance->whowas_fifo.erase(safeiter);
+ ServerInstance->whowas.erase(iter);
+ ServerInstance->whowas_fifo.pop_front();
}
- else {
- /* also trim individual groupsizes in case groupsize should have been lowered */
- whowas_set* n = (whowas_set*)ServerInstance->whowas.find(iter->second)->second;
- if (n->size())
+ else
+ break;
+ }
+
+ /* Then cut the whowas sets to new size (groupsize) */
+ for (int i = 0; i < fifosize; i++)
+ {
+ iter = ServerInstance->whowas.find(ServerInstance->whowas_fifo[0].second);
+ /* hopefully redundant integrity check, but added while debugging r6216 */
+ if (iter == ServerInstance->whowas.end())
+ {
+ /* this should never happen, if it does maps are corrupt */
+ ServerInstance->Log(DEBUG, "Whowas maps got corrupted! (2)");
+ return;
+ }
+ whowas_set* n = (whowas_set*)iter->second;
+ if (n->size())
+ {
+ int nickcount = n->size();
+ while (n->begin() != n->end() && nickcount > groupsize)
{
- int nickcount = n->size();
- while (n->begin() != n->end() && nickcount > groupsize)
- {
- WhoWasGroup *a = *(n->begin());
- DELETE(a);
- n->erase(n->begin());
- nickcount--;
- }
+ WhoWasGroup *a = *(n->begin());
+ DELETE(a);
+ n->pop_front();
+ nickcount--;
}
}
- groupcount--;
}
}
};
@@ -977,15 +989,32 @@ void userrec::AddToWhoWas()
if (iter == ServerInstance->whowas.end())
{
ServerInstance->Log(DEBUG,"Adding new whowas set for %s",this->nick);
+
irc::whowas::whowas_set* n = new irc::whowas::whowas_set;
irc::whowas::WhoWasGroup *a = new irc::whowas::WhoWasGroup(this);
n->push_back(a);
ServerInstance->whowas[this->nick] = n;
ServerInstance->whowas_fifo.push_back(std::make_pair(ServerInstance->Time(),this->nick));
+
if ((int)(ServerInstance->whowas.size()) > ServerInstance->Config->WhoWasMaxGroups)
{
- ServerInstance->Log(DEBUG,"Maxgroups of %d reached deleting oldest group '%s'",ServerInstance->Config->WhoWasMaxGroups, ServerInstance->whowas_fifo.begin()->second.c_str());
- ServerInstance->whowas.erase(ServerInstance->whowas_fifo.begin()->second);
+ ServerInstance->Log(DEBUG,"Maxgroups of %d reached deleting oldest group '%s'",ServerInstance->Config->WhoWasMaxGroups, ServerInstance->whowas_fifo[0].second.c_str());
+
+ irc::whowas::whowas_users::iterator iter = ServerInstance->whowas.find(ServerInstance->whowas_fifo[0].second);
+ if (iter != ServerInstance->whowas.end())
+ {
+ irc::whowas::whowas_set* n = (irc::whowas::whowas_set*)iter->second;
+ if (n->size())
+ {
+ while (n->begin() != n->end())
+ {
+ irc::whowas::WhoWasGroup *a = *(n->begin());
+ DELETE(a);
+ n->pop_front();
+ }
+ }
+ ServerInstance->whowas.erase(iter);
+ }
ServerInstance->whowas_fifo.pop_front();
}
}
@@ -995,16 +1024,16 @@ void userrec::AddToWhoWas()
ServerInstance->Log(DEBUG,"Using existing whowas group for %s",this->nick);
- if ((int)(group->size()) >= ServerInstance->Config->WhoWasGroupSize)
+ irc::whowas::WhoWasGroup *a = new irc::whowas::WhoWasGroup(this);
+ group->push_back(a);
+
+ if ((int)(group->size()) > ServerInstance->Config->WhoWasGroupSize)
{
ServerInstance->Log(DEBUG,"Trimming existing group '%s' to %d entries",this->nick, ServerInstance->Config->WhoWasGroupSize);
irc::whowas::WhoWasGroup *a = (irc::whowas::WhoWasGroup*)*(group->begin());
DELETE(a);
group->pop_front();
}
-
- irc::whowas::WhoWasGroup *a = new irc::whowas::WhoWasGroup(this);
- group->push_back(a);
}
}