From 320f600cd980230b2b2e34c7256c9564af6afae9 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Wed, 10 Jun 2020 19:01:39 +0200 Subject: Add some basic memory tracking infrastructure while hacking --- announce.c | 1 + cfgdir.c | 4 +-- config.c | 6 ++-- idle.c | 2 +- main.c | 8 +++-- proxy.c | 4 +-- rcon.c | 3 +- server.c | 40 ++++++++++++++---------- systemd.c | 104 ++----------------------------------------------------------- uring.c | 2 +- utils.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ utils.h | 13 +++++--- 12 files changed, 147 insertions(+), 135 deletions(-) diff --git a/announce.c b/announce.c index a17bd9a..797807b 100644 --- a/announce.c +++ b/announce.c @@ -96,6 +96,7 @@ announce_free(struct uring_task *task) struct announce *aev = container_of(task, struct announce, task); fprintf(stderr, "%s: called with task 0x%p and aev 0x%p\n", __func__, task, aev); + xfree(aev); } void diff --git a/cfgdir.c b/cfgdir.c index ff35707..4322fec 100644 --- a/cfgdir.c +++ b/cfgdir.c @@ -287,7 +287,7 @@ inotify_free(struct uring_task *task) if (!iev || !cfg) die("%s: iev or cfg is NULL!?\n", __func__); - free(iev); + xfree(iev); cfg->iev = NULL; uring_task_put(cfg, &cfg->task); } @@ -412,7 +412,7 @@ cfgdir_init(struct cfg *cfg) struct dirent *dent; struct server *scfg; - iev = malloc(sizeof(*iev)); + iev = zmalloc(sizeof(*iev)); if (!iev) perrordie("malloc"); diff --git a/config.c b/config.c index e5d4cc7..86723fe 100644 --- a/config.c +++ b/config.c @@ -145,7 +145,7 @@ strtosockaddrs(const char *str, struct list_head *list) list_add(&addr->list, list); goto success; } else { - free(addr); + xfree(addr); } struct addrinfo hints = { @@ -196,7 +196,7 @@ strtosockaddrs(const char *str, struct list_head *list) } default: fprintf(stderr, " Fam: Unknown (%i)\n", ai->ai_family); - free(addr); + xfree(addr); continue; } } @@ -249,7 +249,7 @@ out: list_for_each_entry_safe(addr, tmpaddr, list, list) { list_del(&addr->list); - free(addr); + xfree(addr); } } return false; diff --git a/idle.c b/idle.c index f17d161..5a60973 100644 --- a/idle.c +++ b/idle.c @@ -400,7 +400,7 @@ idle_free(struct uring_task *task) fprintf(stderr, "%s: called with task 0x%p and idle 0x%p\n", __func__, task, idle); idle->server->idle = NULL; - free(idle); + xfree(idle); } void diff --git a/main.c b/main.c index 615231c..4471064 100644 --- a/main.c +++ b/main.c @@ -64,7 +64,7 @@ cfg_free(struct uring_task *task) fprintf(stderr, "%s: called\n", __func__); systemd_delete(cfg); - free(cfg); + xfree(cfg); fprintf(stderr, "All resources free, exiting\n"); exiting = true; } @@ -153,7 +153,7 @@ signalfd_free(struct uring_task *task) fprintf(stderr, "%s: called\n", __func__); sev->cfg->sev = NULL; - free(sev); + xfree(sev); } static void @@ -305,7 +305,7 @@ main(int argc, char **argv) announce_init(cfg); - //announce_start(cfg->aev); + announce_start(cfg->aev); uring_task_put(cfg, &cfg->task); @@ -313,5 +313,7 @@ main(int argc, char **argv) fprintf(stderr, "Event loop exited\n"); + debug_resource_usage(); + exit(EXIT_SUCCESS); } diff --git a/proxy.c b/proxy.c index 98a5af1..6699c39 100644 --- a/proxy.c +++ b/proxy.c @@ -19,7 +19,7 @@ proxy_client_free(struct uring_task *task) fprintf(stderr, "%s: %s\n", __func__, proxy->scfg->name); /* list_del(&proxy->list); - free(proxy); + xfree(proxy); */ } @@ -31,7 +31,7 @@ proxy_server_free(struct uring_task *task) fprintf(stderr, "%s: %s\n", __func__, proxy->scfg->name); /* list_del(&proxy->list); - free(proxy); + xfree(proxy); */ } diff --git a/rcon.c b/rcon.c index a9a6328..be2f279 100644 --- a/rcon.c +++ b/rcon.c @@ -31,7 +31,7 @@ rcon_free(struct uring_task *task) fprintf(stderr, "%s: called with task 0x%p and idle 0x%p\n", __func__, task, rcon); rcon->server->rcon = NULL; - free(rcon); + xfree(rcon); } void @@ -53,6 +53,7 @@ rcon_delete(struct cfg *cfg, struct server *server) fprintf(stderr, "%s called, closing fd %i\n", __func__, rcon->task.fd); uring_cancel(cfg, &rcon->task); + /* FIXME: Won't the refcount be wrong? */ uring_task_put(cfg, &rcon->task); server->rcon = NULL; } diff --git a/server.c b/server.c index 6443c7a..1750e58 100644 --- a/server.c +++ b/server.c @@ -34,7 +34,7 @@ set_property(struct cfg *cfg, struct server *scfg, char **property, const char * if (!cfg || !scfg || empty_str(value) || *property) return false; - *property = strdup(value); + *property = xstrdup(value); if (!*property) { perror("strdup"); return false; @@ -65,13 +65,14 @@ server_free(struct uring_task *task) fprintf(stderr, "Freeing scfg %s\n", scfg->name); list_del(&scfg->list); - free(scfg->pretty_name); - free(scfg->start_exec); - free(scfg->stop_exec); - free(scfg->systemd_service); - free(scfg->systemd_obj); - free(scfg->name); - free(scfg); + xfree(scfg->pretty_name); + xfree(scfg->start_exec); + xfree(scfg->stop_exec); + xfree(scfg->systemd_service); + xfree(scfg->systemd_obj); + xfree(scfg->rcon_password); + xfree(scfg->name); + xfree(scfg); } void @@ -79,6 +80,7 @@ server_delete(struct cfg *cfg, struct server *scfg) { struct server_local *local, *ltmp; struct sockaddr_in46 *remote, *rtmp; + struct sockaddr_in46 *rcon, *rctmp; fprintf(stderr, "Removing server cfg: %s\n", scfg->name); @@ -87,7 +89,12 @@ server_delete(struct cfg *cfg, struct server *scfg) list_for_each_entry_safe(remote, rtmp, &scfg->remotes, list) { list_del(&remote->list); - free(remote); + xfree(remote); + } + + list_for_each_entry_safe(rcon, rctmp, &scfg->rcons, list) { + list_del(&rcon->list); + xfree(rcon); } list_for_each_entry_safe(local, ltmp, &scfg->locals, list) { @@ -120,6 +127,7 @@ server_dump(struct server *scfg) { struct server_local *local; struct sockaddr_in46 *remote; + struct sockaddr_in46 *rcon; char abuf[ADDRSTRLEN]; fprintf(stderr, "\nDumping server %s\n", scfg->name); @@ -143,8 +151,8 @@ server_dump(struct server *scfg) list_for_each_entry(remote, &scfg->remotes, list) fprintf(stderr, " * %s\n", sockaddr_to_str(remote, abuf, sizeof(abuf))); fprintf(stderr, " * RCon:\n"); - list_for_each_entry(remote, &scfg->rcons, list) - fprintf(stderr, " * %s\n", sockaddr_to_str(remote, abuf, sizeof(abuf))); + list_for_each_entry(rcon, &scfg->rcons, list) + fprintf(stderr, " * %s\n", sockaddr_to_str(rcon, abuf, sizeof(abuf))); fprintf(stderr, "\n"); } @@ -156,7 +164,7 @@ server_local_free(struct uring_task *task) fprintf(stderr, "%s called: task 0x%p\n", __func__, task); list_del(&local->list); - free(local); + xfree(local); } static void @@ -540,7 +548,7 @@ server_add_local(struct cfg *cfg, struct server *scfg, struct sockaddr_in46 *add sockaddr_to_str(&local->addr, local->addrstr, sizeof(local->addrstr)); fprintf(stderr, "Adding local: %s\n", local->addrstr); list_add(&local->list, &scfg->locals); - free(addr); + xfree(addr); return true; } @@ -574,11 +582,11 @@ server_set_systemd_service(struct cfg *cfg, struct server *scfg, suffix = strrchr(service, '.'); if (!suffix || strcmp(suffix, ".service")) { - tmp = malloc(strlen(service) + strlen(".service") + 1); + tmp = zmalloc(strlen(service) + strlen(".service") + 1); if (tmp) sprintf(tmp, "%s.service", service); } else - tmp = strdup(service); + tmp = xstrdup(service); if (!tmp) { perror("malloc/strdup"); @@ -691,7 +699,7 @@ server_new(struct cfg *cfg, const char *name) } scfg->type = SERVER_TYPE_UNDEFINED; - scfg->name = strdup(name); + scfg->name = xstrdup(name); scfg->running = false; scfg->stop_method = SERVER_STOP_METHOD_UNDEFINED; scfg->start_method = SERVER_START_METHOD_UNDEFINED; diff --git a/systemd.c b/systemd.c index f556a55..a4dc53f 100644 --- a/systemd.c +++ b/systemd.c @@ -41,7 +41,7 @@ systemd_service_object_path(struct cfg *cfg, const char *service) return NULL; } - r = malloc(strlen(SYSTEMD_DBUS_PATH_PREFIX) + strlen(service) * 3 + 1); + r = zmalloc(strlen(SYSTEMD_DBUS_PATH_PREFIX) + strlen(service) * 3 + 1); if (!r) return NULL; @@ -140,7 +140,7 @@ systemd_service_running(struct cfg *cfg, struct server *server) server->systemd_service, server->systemd_obj); out: - free(status); + xfree(status); sd_bus_error_free(&error); return running; } @@ -219,103 +219,3 @@ systemd_service_start(struct cfg *cfg, struct server *server) return systemd_service_action(cfg, server, "Start"); } - -#if 0 - - - - -int main(int argc, char *argv[]) { - sd_bus_error error = SD_BUS_ERROR_NULL; - sd_bus_message *m = NULL; - sd_bus *bus = NULL; - const char *path; - int r; - - /* Connect to the system bus */ - r = sd_bus_open_user(&bus); - if (r < 0) { - fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-r)); - goto finish; - } - - /* Issue the method call and store the respons message in m */ - r = sd_bus_call_method(bus, - "org.freedesktop.systemd1", /* service to contact */ - "/org/freedesktop/systemd1", /* object path */ - "org.freedesktop.systemd1.Manager", /* interface name */ - "StartUnit", /* method name */ - &error, /* object to return error in */ - &m, /* return message on success */ - "ss", /* input signature */ - "apa.service", /* first argument */ - "fail"); /* second argument */ - if (r < 0) { - fprintf(stderr, "Failed to issue method call: %s\n", error.message); - goto finish; - } - - /* Parse the response message */ - r = sd_bus_message_read(m, "o", &path); - if (r < 0) { - fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r)); - goto finish; - } - printf("Queued service job as %s.\n", path); - - sd_bus_error_free(&error); - sd_bus_message_unref(m); - error = SD_BUS_ERROR_NULL; - m = NULL; - - /* - gdbus call --session - --dest org.freedesktop.systemd1 - --object-path /org/freedesktop/systemd1/unit/myapa_40local2_2eservice - --method org.freedesktop.systemd1.Unit.Start "fail" - - gdbus introspect --session - --dest org.freedesktop.systemd1 - --object-path /org/freedesktop/systemd1/unit/myapa_40local_2eservice - - gdbus call --session - --dest org.freedesktop.systemd1 - --object-path /org/freedesktop/systemd1/unit/myapa_40basker_2eservice - --method org.freedesktop.DBus.Properties.Get - "org.freedesktop.systemd1.Unit" - "ActiveState" - */ - char *res; - r = sd_bus_get_property_string(bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1/unit/apa_2eservice", - "org.freedesktop.systemd1.Unit", - "ActiveState", - &error, - &res); - if (r < 0) { - fprintf(stderr, "Failed to issue prop call: %s\n", error.message); - goto finish; - } - - fprintf(stderr, "RESULT: %s\n", res); -/* - int sd_bus_get_property_string(sd_bus *bus, - const char *destination, - const char *path, - const char *interface, - const char *member, - sd_bus_error *ret_error, - char **ret); - */ -/* -finish: - sd_bus_error_free(&error); - sd_bus_message_unref(m); - sd_bus_unref(bus); - */ - -finish: - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; -} -#endif diff --git a/uring.c b/uring.c index 58d6f2f..4859ac0 100644 --- a/uring.c +++ b/uring.c @@ -450,7 +450,7 @@ uring_free(struct uring_task *task) io_uring_queue_exit(&uev->uring); uev->cfg->uev = NULL; - free(uev); + xfree(uev); } void diff --git a/utils.c b/utils.c index 87ed0fe..b9a4bed 100644 --- a/utils.c +++ b/utils.c @@ -3,10 +3,105 @@ #include #include #include +#include #include "main.h" #include "utils.h" +static unsigned total_malloc_count = 0; +static int malloc_count = 0; + +LIST_HEAD(malloc_list); + +struct allocation { + void *caller; + void *ptr; + size_t size; + struct list_head list; +}; + +static void +__add_allocation(void *caller, void *ptr, size_t size) +{ + struct allocation *a = malloc(sizeof(*a)); + + a->caller = caller; + a->ptr = ptr; + a->size = size; + list_add(&a->list, &malloc_list); +} + +#define add_allocation(p, s) __add_allocation(__builtin_extract_return_addr(__builtin_return_address(0)), p, s) + +void * +__zmalloc(size_t size) +{ + void *ptr; + + fprintf(stderr, "zmalloc: Allocation size %zi\n", size); + ptr = calloc(1, size); + if (ptr) { + add_allocation(ptr, size); + total_malloc_count++; + malloc_count++; + } + return ptr; +} + +char * +__xstrdup(const char *s) +{ + char *r; + + fprintf(stderr, "xstrdup: Allocation size %zi\n", strlen(s) + 1); + r = strdup(s); + if (r) { + add_allocation(r, strlen(s) + 1); + total_malloc_count++; + malloc_count++; + } + return r; +} + +void +xfree(void *ptr) +{ + struct allocation *a, *tmp; + unsigned delete_count = 0; + + if (!ptr) + return; + free(ptr); + malloc_count--; + + list_for_each_entry_safe(a, tmp, &malloc_list, list) { + if (a->ptr == ptr) { + list_del(&a->list); + free(a); + delete_count++; + } + } + + if (delete_count != 1) { + error("Delete count is %u for ptr 0x%p\n", delete_count, ptr); + exit(EXIT_FAILURE); + } +} + +void +debug_resource_usage() +{ + struct allocation *a; + + fprintf(stderr, "Still malloced %i (total %u)\n", + malloc_count, total_malloc_count); + + list_for_each_entry(a, &malloc_list, list) { + fprintf(stderr, "* Allocation - caller: 0x%p, ptr: 0x%p, size %zu\n", + a->caller, a->ptr, a->size); + } +} + uint16_t sockaddr_port(struct sockaddr_in46 *addr) { switch (addr->storage.ss_family) { diff --git a/utils.h b/utils.h index 81ffdb8..2eeb5d4 100644 --- a/utils.h +++ b/utils.h @@ -79,10 +79,15 @@ static inline bool list_empty(struct list_head *list) &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member)) -static inline void* zmalloc(size_t size) -{ - return calloc(1, size); -} +#define zmalloc(s) ({ fprintf(stderr, "Alloc: zmalloc called from %s: %zu\n", __func__, s); __zmalloc(s); }) +void *__zmalloc(size_t s); + +#define xstrdup(s) ({ fprintf(stderr, "Alloc: xstrdup called from %s: %zu\n", __func__, strlen(s) + 1); __xstrdup(s); }) +char *__xstrdup(const char *s); + +void xfree(void *ptr); + +void debug_resource_usage(); #define ADDRSTRLEN (9 /*strlen("AF_INETX ")*/ + INET6_ADDRSTRLEN + 6 /*strlen(" 65535")*/ + 1) struct sockaddr_in46 { -- cgit v1.2.3