summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2013-01-03 11:41:32 -0500
committerAdam <Adam@anope.org>2013-01-03 12:34:01 -0500
commit098157dca8a4aecc18294cbc31cbe5ee95b35a94 (patch)
tree654f00f21e151ba9007ca8eb044a78fef1bd6e39 /src
parent827469600e8cf98fea7aec09ceaa77a097300b72 (diff)
Don't delete users immediately when quit or killed, instead wait until message processing is done
Diffstat (limited to 'src')
-rw-r--r--src/command.cpp9
-rw-r--r--src/messages.cpp2
-rw-r--r--src/nickalias.cpp2
-rw-r--r--src/servers.cpp3
-rw-r--r--src/socket_transport.cpp37
-rw-r--r--src/uplink.cpp9
-rw-r--r--src/users.cpp50
7 files changed, 64 insertions, 48 deletions
diff --git a/src/command.cpp b/src/command.cpp
index 887967626..c737897e5 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -262,13 +262,10 @@ void RunCommand(CommandSource &source, const Anope::string &message)
return;
}
- bool had_u = source.GetUser(), had_nc = source.nc;
- Reference<User> user_reference(source.GetUser());
Reference<NickCore> nc_reference(source.nc);
c->Execute(source, params);
- if (had_u == user_reference && had_nc == nc_reference)
- {
- FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, c, params));
- }
+ if (!nc_reference)
+ source.nc = NULL;
+ FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, c, params));
}
diff --git a/src/messages.cpp b/src/messages.cpp
index 79a32347b..68ba704d1 100644
--- a/src/messages.cpp
+++ b/src/messages.cpp
@@ -351,7 +351,7 @@ void Quit::Run(MessageSource &source, const std::vector<Anope::string> &params)
na->last_quit = reason;
}
FOREACH_MOD(I_OnUserQuit, OnUserQuit(user, reason));
- delete user;
+ user->Quit(reason);
return;
}
diff --git a/src/nickalias.cpp b/src/nickalias.cpp
index 4ce861943..cee24fb87 100644
--- a/src/nickalias.cpp
+++ b/src/nickalias.cpp
@@ -88,7 +88,7 @@ void NickAlias::Release()
User *u = User::Find(this->nick);
if (u && u->server == Me)
{
- delete u;
+ u->Quit();
}
}
diff --git a/src/servers.cpp b/src/servers.cpp
index 392e494a0..fd3fe490a 100644
--- a/src/servers.cpp
+++ b/src/servers.cpp
@@ -137,7 +137,8 @@ Server::~Server()
na->last_quit = this->quit_reason;
}
- delete u;
+ u->Quit(this->quit_reason);
+ u->server = NULL;
}
}
diff --git a/src/socket_transport.cpp b/src/socket_transport.cpp
index 4af3668a3..98da3e605 100644
--- a/src/socket_transport.cpp
+++ b/src/socket_transport.cpp
@@ -33,34 +33,9 @@ bool BufferedSocket::ProcessRead()
return false;
tbuffer[len] = 0;
+ this->read_buffer.append(tbuffer);
this->recv_len = len;
- Anope::string sbuffer = this->extra_buf;
- sbuffer += tbuffer;
- this->extra_buf.clear();
- size_t lastnewline = sbuffer.rfind('\n');
- if (lastnewline == Anope::string::npos)
- {
- this->extra_buf = sbuffer;
- return true;
- }
- if (lastnewline < sbuffer.length() - 1)
- {
- this->extra_buf = sbuffer.substr(lastnewline);
- this->extra_buf.trim();
- sbuffer = sbuffer.substr(0, lastnewline);
- }
-
- sepstream stream(sbuffer, '\n');
-
- Anope::string tbuf;
- while (stream.GetToken(tbuf))
- {
- tbuf.trim();
- if (!Read(tbuf))
- return false;
- }
-
return true;
}
@@ -76,9 +51,15 @@ bool BufferedSocket::ProcessWrite()
return true;
}
-bool BufferedSocket::Read(const Anope::string &buf)
+const Anope::string BufferedSocket::GetLine()
{
- return false;
+ size_t s = this->read_buffer.find('\n');
+ if (s == Anope::string::npos)
+ return "";
+ Anope::string str = this->read_buffer.substr(0, s + 1);
+ this->read_buffer.erase(0, s + 1);
+ this->read_buffer.ltrim();
+ return str.trim();
}
void BufferedSocket::Write(const char *buffer, size_t l)
diff --git a/src/uplink.cpp b/src/uplink.cpp
index 9490329b3..7c9c77888 100644
--- a/src/uplink.cpp
+++ b/src/uplink.cpp
@@ -116,9 +116,14 @@ UplinkSocket::~UplinkSocket()
}
}
-bool UplinkSocket::Read(const Anope::string &buf)
+bool UplinkSocket::ProcessRead()
{
- Anope::Process(buf);
+ BufferedSocket::ProcessRead();
+ for (Anope::string buf; (buf = this->GetLine()).empty() == false;)
+ {
+ Anope::Process(buf);
+ User::QuitUsers();
+ }
return true;
}
diff --git a/src/users.cpp b/src/users.cpp
index 0e2ed34f9..1f70b47b4 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -30,12 +30,15 @@ int OperCount = 0;
unsigned MaxUserCount = 0;
time_t MaxUserTime = 0;
+std::list<User *> User::quitting_users;
+
User::User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ssignon, const Anope::string &smodes, const Anope::string &suid)
{
if (snick.empty() || sident.empty() || shost.empty())
throw CoreException("Bad args passed to User::User");
/* we used to do this by calloc, no more. */
+ quit = false;
server = NULL;
invalid_pw_count = invalid_pw_time = lastmemosend = lastnickreg = lastmail = 0;
on_access = false;
@@ -79,8 +82,7 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope:
bool exempt = false;
if (server && server->IsULined())
exempt = true;
- Reference<User> user = this;
- FOREACH_MOD(I_OnUserConnect, OnUserConnect(user, exempt));
+ FOREACH_MOD(I_OnUserConnect, OnUserConnect(this, exempt));
}
void User::ChangeNick(const Anope::string &newnick, time_t ts)
@@ -229,10 +231,11 @@ void User::SetRealname(const Anope::string &srealname)
User::~User()
{
- Log(LOG_DEBUG_2) << "User::~User() called";
-
- Log(this, "disconnect") << "(" << this->realname << ") " << "disconnected from the network (" << this->server->GetName() << ")";
- --this->server->users;
+ if (this->server != NULL)
+ {
+ Log(this, "disconnect") << "(" << this->realname << ") disconnected from the network (" << this->server->GetName() << ")";
+ --this->server->users;
+ }
FOREACH_MOD(I_OnUserLogoff, OnUserLogoff(this));
@@ -252,8 +255,6 @@ User::~User()
NickAlias *na = NickAlias::Find(this->nick);
if (na)
na->OnCancel(this);
-
- Log(LOG_DEBUG_2) << "User::~User() done";
}
void User::SendMessage(const BotInfo *source, const char *fmt, ...)
@@ -752,6 +753,12 @@ void User::Kill(const Anope::string &source, const Anope::string &reason)
void User::KillInternal(const Anope::string &source, const Anope::string &reason)
{
+ if (this->quit)
+ {
+ Log(LOG_DEBUG) << "Duplicate quit for " << this->nick;
+ return;
+ }
+
Log(this, "killed") << "was killed by " << source << " (Reason: " << reason << ")";
NickAlias *na = NickAlias::Find(this->nick);
@@ -761,7 +768,25 @@ void User::KillInternal(const Anope::string &source, const Anope::string &reason
na->last_quit = reason;
}
- delete this;
+ this->quit = true;
+ quitting_users.push_back(this);
+}
+
+void User::Quit(const Anope::string &reason)
+{
+ if (this->quit)
+ {
+ Log(LOG_DEBUG) << "Duplicate quit for " << this->nick;
+ return;
+ }
+
+ this->quit = true;
+ quitting_users.push_back(this);
+}
+
+bool User::Quitting() const
+{
+ return this->quit;
}
Anope::string User::Mask() const
@@ -829,3 +854,10 @@ User* User::Find(const Anope::string &name, bool nick_only)
return NULL;
}
+void User::QuitUsers()
+{
+ for (std::list<User *>::iterator it = quitting_users.begin(), it_end = quitting_users.end(); it != it_end; ++it)
+ delete *it;
+ quitting_users.clear();
+}
+