summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2015-09-17 10:07:30 -0400
committerAdam <Adam@anope.org>2015-09-17 10:07:30 -0400
commit1ac4a1d9a56141d18b3e8a32fe165535031a4c67 (patch)
tree5ee8af16acaaad7307732213afaf9eaa333a76d2 /src
parent8d13a355cd9b851b5cf9f6012c77b2af68a039f1 (diff)
Defer channel deletion until after i/o. There are some edge cases with events kicking users mid-event that can delete them.
Diffstat (limited to 'src')
-rw-r--r--src/bots.cpp5
-rw-r--r--src/channels.cpp22
-rw-r--r--src/messages.cpp8
-rw-r--r--src/uplink.cpp1
4 files changed, 22 insertions, 14 deletions
diff --git a/src/bots.cpp b/src/bots.cpp
index c6a726855..bc8b75594 100644
--- a/src/bots.cpp
+++ b/src/bots.cpp
@@ -219,12 +219,9 @@ void BotInfo::Part(Channel *c, const Anope::string &reason)
IRCD->SendPart(this, c, "%s", !reason.empty() ? reason.c_str() : "");
- Anope::string cname = c->name;
- Reference<Channel> cref = c;
-
c->DeleteUser(this);
- FOREACH_MOD(OnPartChannel, (this, cref, cname, reason));
+ FOREACH_MOD(OnPartChannel, (this, c, c->name, reason));
}
void BotInfo::OnMessage(User *u, const Anope::string &message)
diff --git a/src/channels.cpp b/src/channels.cpp
index a794f5126..8e9b3be94 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -27,6 +27,7 @@
#include "uplink.h"
channel_map ChannelList;
+std::vector<Channel *> Channel::deleting;
Channel::Channel(const Anope::string &nname, time_t ts)
{
@@ -168,8 +169,8 @@ void Channel::DeleteUser(User *user)
Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete non-existent channel " << this->name << " from " << user->nick << "'s channel list";
delete cu;
- if (this->CheckDelete())
- delete this;
+ if (std::find(deleting.begin(), deleting.end(), this) == deleting.end())
+ deleting.push_back(this);
}
ChanUserContainer *Channel::FindUser(User *u) const
@@ -759,12 +760,11 @@ void Channel::KickInternal(const MessageSource &source, const Anope::string &nic
return;
}
- Anope::string this_name = this->name;
ChannelStatus status = cu->status;
FOREACH_MOD(OnPreUserKicked, (source, cu, reason));
- this->DeleteUser(target); /* This can delete this; */
- FOREACH_MOD(OnUserKicked, (source, target, this_name, status, reason));
+ this->DeleteUser(target);
+ FOREACH_MOD(OnUserKicked, (source, target, this->name, status, reason));
}
bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...)
@@ -939,3 +939,15 @@ Channel *Channel::FindOrCreate(const Anope::string &name, bool &created, time_t
return chan;
}
+void Channel::DeleteChannels()
+{
+ for (unsigned int i = 0; i < deleting.size(); ++i)
+ {
+ Channel *c = deleting[i];
+
+ if (c->CheckDelete())
+ delete c;
+ }
+ deleting.clear();
+}
+
diff --git a/src/messages.cpp b/src/messages.cpp
index 4e1bcd0db..1c035238f 100644
--- a/src/messages.cpp
+++ b/src/messages.cpp
@@ -84,10 +84,9 @@ void Join::Run(MessageSource &source, const std::vector<Anope::string> &params)
ChanUserContainer *cc = it->second;
++it;
- Anope::string channame = cc->chan->name;
FOREACH_MOD(OnPrePartChannel, (user, cc->chan));
cc->chan->DeleteUser(user);
- FOREACH_MOD(OnPartChannel, (user, Channel::Find(channame), channame, ""));
+ FOREACH_MOD(OnPartChannel, (user, cc->chan, cc->chan->name, ""));
}
continue;
}
@@ -284,16 +283,15 @@ void Part::Run(MessageSource &source, const std::vector<Anope::string> &params)
while (sep.GetToken(channel))
{
- Reference<Channel> c = Channel::Find(channel);
+ Channel *c = Channel::Find(channel);
if (!c || !u->FindChannel(c))
continue;
Log(u, c, "part") << "Reason: " << (!reason.empty() ? reason : "No reason");
FOREACH_MOD(OnPrePartChannel, (u, c));
- Anope::string ChannelName = c->name;
c->DeleteUser(u);
- FOREACH_MOD(OnPartChannel, (u, c, ChannelName, !reason.empty() ? reason : ""));
+ FOREACH_MOD(OnPartChannel, (u, c, c->name, !reason.empty() ? reason : ""));
}
}
diff --git a/src/uplink.cpp b/src/uplink.cpp
index 86851fc50..6171e2353 100644
--- a/src/uplink.cpp
+++ b/src/uplink.cpp
@@ -136,6 +136,7 @@ bool UplinkSocket::ProcessRead()
{
Anope::Process(buf);
User::QuitUsers();
+ Channel::DeleteChannels();
}
return b;
}