summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-21 23:42:05 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-21 23:42:05 +0200
commit2b2d6ad0541544074fd54c86af6de2e2947e62ce (patch)
tree84dee7bca11631193a86ee62e50916a3adc32ef4
parent0ba4f18ea6981b4d2b4eded11b2da4b2a2192d5b (diff)
Move mcast task to a per-server task to get refcounting right
-rw-r--r--announce.c82
-rw-r--r--main.c13
-rw-r--r--main.h4
-rw-r--r--server.c55
-rw-r--r--server.h7
-rw-r--r--uring.c8
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 <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
+#include <unistd.h>
#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!");