summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2015-06-13 23:41:54 +0200
committerPřemysl Janouch <p.janouch@gmail.com>2015-06-13 23:41:54 +0200
commitd25377599ce8d8ef019a7ae5467aadb7e8a2dbf8 (patch)
tree25734b424bb82c68153c87f363c7390f71ae0244
parentabc0e4f821568e135623d035312d7a92f5f507cc (diff)
downloadxK-d25377599ce8d8ef019a7ae5467aadb7e8a2dbf8.tar.gz
xK-d25377599ce8d8ef019a7ae5467aadb7e8a2dbf8.tar.xz
xK-d25377599ce8d8ef019a7ae5467aadb7e8a2dbf8.zip
kike: fix quitting + code shuffling
-rw-r--r--kike.c70
1 files changed, 33 insertions, 37 deletions
diff --git a/kike.c b/kike.c
index 602f654..9d3878b 100644
--- a/kike.c
+++ b/kike.c
@@ -388,7 +388,8 @@ client_free (struct client *self)
str_map_free (&self->invites);
}
-static void client_close_link (struct client *, const char *);
+static void client_close_link (struct client *c, const char *reason);
+static void client_kill (struct client *c, const char *reason);
static void client_send (struct client *, const char *, ...)
ATTRIBUTE_PRINTF (2, 3);
static void client_cancel_timers (struct client *);
@@ -623,8 +624,13 @@ static void
on_irc_quit_timeout (void *user_data)
{
struct server_context *ctx = user_data;
- // Clients are closed in server_context_free()
- ctx->polling = false;
+ struct client *iter, *next;
+ for (iter = ctx->clients; iter; iter = next)
+ {
+ next = iter->next;
+ // irc_initiate_quit() has already unregistered the client
+ client_kill (iter, "Shutting down");
+ }
}
static void
@@ -676,19 +682,9 @@ server_context_free (struct server_context *self)
free (self->listen_fds);
free (self->listen_events);
+ hard_assert (!self->clients);
if (self->ssl_ctx)
SSL_CTX_free (self->ssl_ctx);
- struct client *link, *tmp;
- for (link = self->clients; link; link = tmp)
- {
- tmp = link->next;
- // FIXME: either make sure this isn't called (which it can as of now,
- // see on_irc_quit_timeout) or fix client_free() to unregister from
- // the poller before closing the socket (we could also just
- // set .closed = true).
- client_free (link);
- free (link);
- }
free (self->server_name);
str_map_free (&self->users);
@@ -729,10 +725,6 @@ irc_initiate_quit (struct server_context *ctx)
{
print_status ("shutting down");
- for (struct client *iter = ctx->clients; iter; iter = iter->next)
- if (!iter->closing_link)
- client_close_link (iter, "Shutting down");
-
for (size_t i = 0; i < ctx->n_listen_fds; i++)
{
xclose (ctx->listen_fds[i]);
@@ -741,6 +733,10 @@ irc_initiate_quit (struct server_context *ctx)
}
ctx->n_listen_fds = 0;
+ for (struct client *iter = ctx->clients; iter; iter = iter->next)
+ if (!iter->closing_link)
+ client_close_link (iter, "Shutting down");
+
ctx->quitting = true;
poller_timer_set (&ctx->quit_timer, 5000);
irc_try_finish_quit (ctx);
@@ -889,6 +885,25 @@ client_unregister (struct client *c, const char *reason)
}
static void
+client_close_link (struct client *c, const char *reason)
+{
+ if (!soft_assert (!c->closing_link))
+ return;
+
+ // We push an `ERROR' message to the write buffer and let the poller send
+ // it, with some arbitrary timeout. The `closing_link' state makes sure
+ // that a/ we ignore any successive messages, and b/ that the connection
+ // is killed after the write buffer is transferred and emptied.
+ client_send (c, "ERROR :Closing Link: %s[%s] (%s)",
+ c->nickname ? c->nickname : "*",
+ c->hostname /* TODO host IP? */, reason);
+ c->closing_link = true;
+
+ client_unregister (c, reason);
+ client_set_kill_timer (c);
+}
+
+static void
client_kill (struct client *c, const char *reason)
{
client_unregister (c, reason ? reason : "Client exited");
@@ -917,25 +932,6 @@ client_kill (struct client *c, const char *reason)
irc_try_finish_quit (ctx);
}
-static void
-client_close_link (struct client *c, const char *reason)
-{
- if (!soft_assert (!c->closing_link))
- return;
-
- // We push an `ERROR' message to the write buffer and let the poller send
- // it, with some arbitrary timeout. The `closing_link' state makes sure
- // that a/ we ignore any successive messages, and b/ that the connection
- // is killed after the write buffer is transferred and emptied.
- client_send (c, "ERROR :Closing Link: %s[%s] (%s)",
- c->nickname ? c->nickname : "*",
- c->hostname /* TODO host IP? */, reason);
- c->closing_link = true;
-
- client_unregister (c, reason);
- client_set_kill_timer (c);
-}
-
static bool
client_in_mask_list (const struct client *c, const struct str_vector *mask)
{