From 2b2d6ad0541544074fd54c86af6de2e2947e62ce Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 21 Jun 2020 23:42:05 +0200 Subject: Move mcast task to a per-server task to get refcounting right --- announce.c | 82 +++++++------------------------------------------------------- main.c | 13 +++++++--- main.h | 4 +-- server.c | 55 +++++++++++++++++++++++++++++++++++++++++ server.h | 7 ++++-- uring.c | 8 +++--- 6 files changed, 85 insertions(+), 84 deletions(-) diff --git a/announce.c b/announce.c index 9195cd2..f85ba1e 100644 --- a/announce.c +++ b/announce.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "main.h" #include "uring.h" @@ -13,76 +14,14 @@ struct announce { uint64_t value; struct uring_task task; - struct uring_task mcast_task; + int mcast_fd; }; -static void -mcast_free(struct uring_task *task) -{ - struct announce *aev = container_of(task, struct announce, mcast_task); - - assert_return(task); - debug(DBG_ANN, "task %p, aev %p", task, aev); -} - -static void -mcast_sent(struct cfg *cfg, struct uring_task *task, int res) -{ - struct server *server = container_of(task->tbuf, struct server, mcast_buf); - - assert_return(cfg && task && task->tbuf); - - if (res < 0) - error("failure %i", res); - else - debug(DBG_ANN, "result %i", res); - - uring_task_put(cfg, &server->task); -} - -static void -mcast_send(struct cfg *cfg, struct announce *aev, struct server *server) -{ - int len; - - assert_return(cfg && aev && server); - - /* FIXME: should these be assert:ed as well? */ - if (!server->pretty_name || server->announce_port < 1) - return; - - len = snprintf(server->mcast_buf.buf, sizeof(server->mcast_buf.buf), - "[MOTD]%s[/MOTD][AD]%" PRIu16 "[/AD]", - server->pretty_name, server->announce_port); - - if (len < 1 || len >= sizeof(server->mcast_buf.buf)) { - error("snprintf returned %i", len); - return; - } - - server->mcast_buf.len = len; - uring_task_set_buf(&aev->mcast_task, &server->mcast_buf); - uring_task_get(cfg, &server->task); - uring_tbuf_sendmsg(cfg, &aev->mcast_task, mcast_sent); -} - -static void -mcast_send_all(struct cfg *cfg, struct announce *aev) -{ - struct server *server; - - assert_return(cfg && aev); - - list_for_each_entry(server, &cfg->servers, list) { - verbose("Announcing server: %s", server->name); - mcast_send(cfg, aev, server); - } -} - static void announce_cb(struct cfg *cfg, struct uring_task *task, int res) { struct announce *aev = container_of(task, struct announce, task); + struct server *server; assert_return(cfg && task); assert_task_alive(DBG_ANN, task); @@ -93,7 +32,8 @@ announce_cb(struct cfg *cfg, struct uring_task *task, int res) } debug(DBG_ANN, "timerfd value %" PRIu64, aev->value); - mcast_send_all(cfg, aev); + list_for_each_entry(server, &cfg->servers, list) + server_announce(cfg, server, aev->mcast_fd); uring_read(cfg, &aev->task, &aev->value, sizeof(aev->value), announce_cb); } @@ -103,7 +43,9 @@ announce_free(struct uring_task *task) struct announce *aev = container_of(task, struct announce, task); assert_return(task); - debug(DBG_ANN, "task %p, aev 0x%p", task, aev); + debug(DBG_ANN, "task %p, aev 0x%p, mcast_fd: %i", + task, aev, aev->mcast_fd); + close(aev->mcast_fd); xfree(aev); } @@ -113,7 +55,6 @@ announce_refdump(struct announce *aev) assert_return_silent(aev); uring_task_refdump(&aev->task); - uring_task_refdump(&aev->mcast_task); } void @@ -122,7 +63,6 @@ announce_delete(struct cfg *cfg) assert_return(cfg && cfg->aev); debug(DBG_ANN, "closing fd %i", cfg->aev->task.fd); - uring_task_destroy(cfg, &cfg->aev->mcast_task); uring_task_destroy(cfg, &cfg->aev->task); cfg->aev = NULL; } @@ -190,11 +130,7 @@ announce_init(struct cfg *cfg) uring_task_init(cfg, &aev->task, "aev", uring_parent(cfg), announce_free); uring_task_set_fd(&aev->task, afd); - - uring_task_init(cfg, &aev->mcast_task, "aev_mcast", &aev->task, mcast_free); - uring_task_set_fd(&aev->mcast_task, sfd); - saddr_set_ipv4(&aev->mcast_task.saddr, cinet_addr(224,0,2,60), htons(4445)); - + aev->mcast_fd = sfd; cfg->aev = aev; uring_read(cfg, &aev->task, &aev->value, sizeof(aev->value), announce_cb); } diff --git a/main.c b/main.c index 5d99711..1887a5d 100644 --- a/main.c +++ b/main.c @@ -450,10 +450,10 @@ cfg_init(int argc, char **argv) debug_mask = ~0; break; } else if (strcaseeq(optarg, "list")) { - error("Debug categories:"); - error(" * all"); + info("Debug categories:"); + info(" * all"); for (i = 0; debug_category_str[i].name; i++) - error(" * %s", debug_category_str[i].name); + info(" * %s", debug_category_str[i].name); exit(EXIT_FAILURE); } @@ -642,9 +642,16 @@ static void hack_handler(int signum, siginfo_t *info, void *ucontext) { uint64_t val; + static unsigned count = 0; assert_return(signum > 0 && info); + count++; + if (count > 5) { + dump_tree(cfghack); + exit(EXIT_FAILURE); + } + switch (signum) { case SIGUSR1: debug(DBG_SIG, "Got a SIGUSR1"); diff --git a/main.h b/main.h index 9759ecf..5dff164 100644 --- a/main.h +++ b/main.h @@ -88,12 +88,12 @@ void __die(const char *fmt, ...) __attribute__((format(printf, 1, 2))); #define assert_task_alive_or(lvl, t, cmd) \ do { \ if (!(t)) { \ - error("invalid task\n"); \ + error("invalid task"); \ cmd; \ } \ \ if ((t)->dead) { \ - debug((lvl), "task dead\n"); \ + debug((lvl), "task dead"); \ cmd; \ } \ } while(0) diff --git a/server.c b/server.c index 452e45f..4a45b53 100644 --- a/server.c +++ b/server.c @@ -54,6 +54,8 @@ server_refdump(struct server *server) assert_return(server); uring_task_refdump(&server->task); + uring_task_refdump(&server->exec_task); + uring_task_refdump(&server->ann_task); list_for_each_entry(local, &server->locals, list) uring_task_refdump(&local->task); list_for_each_entry(proxy, &server->proxys, list) @@ -94,6 +96,7 @@ server_delete(struct cfg *cfg, struct server *server) assert_return(cfg && server); verbose("Removing server %s", server->name); + server->state = SERVER_STATE_DEAD; idle_delete(cfg, server); rcon_delete(cfg, server); @@ -120,6 +123,7 @@ server_delete(struct cfg *cfg, struct server *server) uring_poll_cancel(cfg, &server->exec_task); uring_task_put(cfg, &server->exec_task); uring_task_destroy(cfg, &server->task); + uring_task_put(cfg, &server->ann_task); } void @@ -452,11 +456,50 @@ server_stop(struct cfg *cfg, struct server *server) return false; } +static void +server_announce_free(struct uring_task *task) +{ + assert_return(task); + + debug(DBG_ANN, "called"); +} + +static void +server_announce_cb(struct cfg *cfg, struct uring_task *task, int res) +{ + struct server *server = container_of(task, struct server, ann_task); + + assert_return(cfg && task); + + if (res < 0) + error("failure %i", res); + else + debug(DBG_ANN, "result %i", res); + + uring_task_set_fd(&server->ann_task, -1); +} + +bool +server_announce(struct cfg *cfg, struct server *server, int fd) +{ + assert_return(cfg && server && fd >= 0, false); + + if (server->state == SERVER_STATE_INIT || + server->state == SERVER_STATE_DEAD) + return false; + + debug(DBG_ANN, "announcing server: %s", server->name); + uring_task_set_fd(&server->ann_task, fd); + uring_tbuf_sendmsg(cfg, &server->ann_task, server_announce_cb); + return true; +} + bool server_commit(struct cfg *cfg, struct server *server) { struct server_local *local; uint16_t port; + int r; assert_return(cfg && server && server->name, false); assert_task_alive_or(DBG_SRV, &server->task, return false); @@ -599,6 +642,15 @@ server_commit(struct cfg *cfg, struct server *server) } } + r = snprintf(server->ann_buf.buf, sizeof(server->ann_buf.buf), + "[MOTD]%s[/MOTD][AD]%" PRIu16 "[/AD]", + server->pretty_name, server->announce_port); + if (r < 1 || r >= sizeof(server->ann_buf.buf)) { + error("%s: unable to create announce msg: %i\n", server->name, r); + return false; + } + server->ann_buf.len = r; + /* FIXME: config, dont reread config if server running, make sure fd is available before this is called */ server_dump(server); @@ -806,6 +858,9 @@ server_new(struct cfg *cfg, const char *name) server->start_method = SERVER_START_METHOD_UNDEFINED; uring_task_init(cfg, &server->task, "server", uring_parent(cfg), server_free); uring_task_set_buf(&server->task, &server->tbuf); + uring_task_init(cfg, &server->ann_task, "announce", &server->task, server_announce_free); + uring_task_set_buf(&server->ann_task, &server->ann_buf); + saddr_set_ipv4(&server->ann_task.saddr, cinet_addr(224,0,2,60), htons(4445)); uring_task_init(cfg, &server->exec_task, "exec", &server->task, server_exec_free); list_init(&server->remotes); list_init(&server->locals); diff --git a/server.h b/server.h index 80400a1..46fac3f 100644 --- a/server.h +++ b/server.h @@ -58,7 +58,8 @@ struct server { char *rcon_password; /* For announce messages */ - struct uring_task_buf mcast_buf; + struct uring_task ann_task; + struct uring_task_buf ann_buf; /* For checking idle status */ struct idle *idle; @@ -66,8 +67,8 @@ struct server { unsigned idle_count; /* For reading config files */ - struct uring_task_buf tbuf; struct uring_task task; + struct uring_task_buf tbuf; struct list_head list; }; @@ -82,6 +83,8 @@ bool server_start(struct cfg *cfg, struct server *server); bool server_stop(struct cfg *cfg, struct server *server); +bool server_announce(struct cfg *cfg, struct server *server, int fd); + bool server_commit(struct cfg *cfg, struct server *server); bool server_add_remote(struct cfg *cfg, struct server *server, diff --git a/uring.c b/uring.c index f08ba9e..88309f8 100644 --- a/uring.c +++ b/uring.c @@ -112,8 +112,8 @@ uring_task_put(struct cfg *cfg, struct uring_task *task) assert_return(cfg && task); - debug(DBG_REF, "task %s (%p), refcount %u", - task->name, task, task->refcount); + debug(DBG_REF, "task %s (%p), refcount %u -> %u", + task->name, task, task->refcount, task->refcount - 1); task->refcount--; @@ -144,8 +144,8 @@ uring_task_get(struct cfg *cfg, struct uring_task *task) { assert_return(cfg && task); - debug(DBG_REF, "task %s (%p), refcount %u", - task->name, task, task->refcount); + debug(DBG_REF, "task %s (%p), refcount %u -> %u", + task->name, task, task->refcount, task->refcount + 1); if (task->refcount < 0) error("Negative refcount!"); -- cgit v1.2.3