From 340127fff23971ce6eaa190510299e1c02c672e9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:20:04 +0900 Subject: [PATCH] [ruamoko] Plug yet more memory leaks Some of them, especially in rua_obj, were quite legitimate and even a problem for thread-safety (rua_cmd is currently not thread-safe, but it needs a lock, which I don't feel like doing at this stage). --- libs/ruamoko/rua_cmd.c | 5 +- libs/ruamoko/rua_gui.c | 40 ++++++++++++---- libs/ruamoko/rua_input.c | 3 +- libs/ruamoko/rua_model.c | 4 +- libs/ruamoko/rua_obj.c | 91 ++++++++++++++++++++++++++---------- libs/ruamoko/rua_scene.c | 5 +- ruamoko/qwaq/builtins/main.c | 6 +++ 7 files changed, 116 insertions(+), 38 deletions(-) diff --git a/libs/ruamoko/rua_cmd.c b/libs/ruamoko/rua_cmd.c index 96025fc65..c147b6990 100644 --- a/libs/ruamoko/rua_cmd.c +++ b/libs/ruamoko/rua_cmd.c @@ -58,6 +58,7 @@ typedef struct { } cmd_resources_t; static hashtab_t *bi_cmds; +static hashctx_t *bi_cmd_hashctx; static int bi_cmds_refs; static const char * @@ -129,6 +130,7 @@ bi_cmd_destroy (progs_t *pr, void *data) { if (!--bi_cmds_refs) { Hash_DelTable (bi_cmds); + Hash_DelContext (bi_cmd_hashctx); } free (data); } @@ -173,8 +175,9 @@ RUA_Cmd_Init (progs_t *pr, int secure) res->cmds = 0; if (!bi_cmds) { + //FIXME not thread-safe bi_cmds = Hash_NewTable (1021, bi_cmd_get_key, bi_cmd_free, 0, - pr->hashctx); + &bi_cmd_hashctx); } bi_cmds_refs++; diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c index 8bd59ad46..98c201716 100644 --- a/libs/ruamoko/rua_gui.c +++ b/libs/ruamoko/rua_gui.c @@ -140,13 +140,13 @@ font_new (gui_resources_t *res) { return PR_RESNEW (res->font_map); } -/* + static void font_free (gui_resources_t *res, rua_font_t *font) { PR_RESFREE (res->font_map, font); } -*/ + static void font_reset (gui_resources_t *res) { @@ -168,16 +168,16 @@ font_index (gui_resources_t *res, rua_font_t *font) static int alloc_font (gui_resources_t *res, font_t *font) { - rua_font_t *psg = font_new (res); + rua_font_t *fnt = font_new (res); - psg->next = res->fonts; - psg->prev = &res->fonts; + fnt->next = res->fonts; + fnt->prev = &res->fonts; if (res->fonts) { - res->fonts->prev = &psg->next; + res->fonts->prev = &fnt->next; } - res->fonts = psg; - psg->font = font; - return font_index (res, psg); + res->fonts = fnt; + fnt->font = font; + return font_index (res, fnt); } static rua_font_t * __attribute__((pure)) @@ -215,6 +215,8 @@ bi_gui_destroy (progs_t *pr, void *_res) { gui_resources_t *res = _res; ECS_DelRegistry (res->reg); + PR_RESDELMAP (res->passage_map); + PR_RESDELMAP (res->font_map); free (res); } @@ -231,6 +233,15 @@ bi (Font_Load) R_INT (pr) = alloc_font (res, font); } +bi (Font_Free) +{ + gui_resources_t *res = _res; + rua_font_t *font = get_font (res, P_INT (pr, 0)); + + Font_Free (font->font); + font_free (res, font); +} + bi (Passage_New) { gui_resources_t *res = _res; @@ -361,6 +372,15 @@ bi (Text_Draw) } } +bi (View_Delete) +{ + gui_resources_t *res = _res; + uint32_t viewid = P_UINT (pr, 0); + view_t view = { .id = viewid, .reg = res->reg, + .comp = res->view_base + view_href }; + View_Delete (view); +} + bi (View_ChildCount) { gui_resources_t *res = _res; @@ -427,6 +447,7 @@ bi (View_UpdateHierarchy) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { bi(Font_Load, 2, p(string), p(int)), + bi(Font_Free, 2, p(int)), bi(Passage_New, 0), bi(Passage_ParseText, 2, p(ptr), p(string)), bi(Passage_Delete, 1, p(ptr)), @@ -436,6 +457,7 @@ static builtin_t builtins[] = { bi(Text_View, 2, p(ptr), p(int)), bi(Text_SetScript, 4, p(uint), p(string), p(int), p (int)), + bi(View_Delete, 1, p(uint)), bi(View_ChildCount, 1, p(uint)), bi(View_GetChild, 2, p(uint), p(uint)), bi(View_SetPos, 3, p(uint), p(int), p(int)), diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index 1c6153b55..df86bcec1 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -519,8 +519,7 @@ RUA_Input_Init (progs_t *pr, int secure) input_resources_t *res = calloc (sizeof (input_resources_t), 1); res->cookie_super = new_memsuper (); - res->cookies = Hash_NewTable (251, 0, rua_in_free_cookie, res, - &res->hashctx); + res->cookies = Hash_NewTable (251, 0, rua_in_free_cookie, res, pr->hashctx); Hash_SetHashCompare (res->cookies, rua_in_hash_cookie, rua_in_cmp_cookies); PR_Resources_Register (pr, "input", res, bi_input_clear, bi_input_destroy); diff --git a/libs/ruamoko/rua_model.c b/libs/ruamoko/rua_model.c index a19fa8f92..055462ec0 100644 --- a/libs/ruamoko/rua_model.c +++ b/libs/ruamoko/rua_model.c @@ -106,7 +106,9 @@ bi_rua_model_clear (progs_t *pr, void *_res) static void bi_rua_model_destroy (progs_t *pr, void *_res) { - free (_res); + rua_model_resources_t *res = _res; + PR_RESDELMAP (res->model_map); + free (res); } static int diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 81c440924..0e1a8ddb8 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -45,6 +45,7 @@ #include "qfalloca.h" #include "QF/cvar.h" +#include "QF/darray.h" #include "QF/dstring.h" #include "QF/hash.h" #include "QF/mathlib.h" @@ -99,6 +100,8 @@ typedef struct obj_list_s { void *data; } obj_list; +typedef struct listset_s DARRAY_TYPE (obj_list *) listset_t; + typedef struct dtable_s { struct dtable_s *next; struct dtable_s **prev; @@ -106,6 +109,13 @@ typedef struct dtable_s { pr_func_t *imp; } dtable_t; +typedef struct class_tree { + pr_class_t *class; + obj_list *subclasses; +} class_tree; + +typedef struct treeset_s DARRAY_TYPE (class_tree *) treeset_t; + typedef struct probj_resources_s { progs_t *pr; unsigned selector_index; @@ -124,6 +134,7 @@ typedef struct probj_resources_s { hashtab_t *classes; hashtab_t *protocols; hashtab_t *load_methods; + listset_t obj_list_sets; obj_list *obj_list_free_list; obj_list *unresolved_classes; obj_list *unclaimed_categories; @@ -131,6 +142,9 @@ typedef struct probj_resources_s { obj_list *unclaimed_proto_list; obj_list *module_list; obj_list *class_tree_list; + + class_tree *class_tree_free_list; + treeset_t class_tree_sets; } probj_t; static dtable_t * @@ -184,8 +198,11 @@ obj_list_new (probj_t *probj) if (!probj->obj_list_free_list) { probj->obj_list_free_list = calloc (128, sizeof (obj_list)); - for (i = 0; i < 127; i++) - probj->obj_list_free_list[i].next = &probj->obj_list_free_list[i + 1]; + for (i = 0; i < 127; i++) { + __auto_type next = &probj->obj_list_free_list[i + 1]; + probj->obj_list_free_list[i].next = next; + } + DARRAY_APPEND (&probj->obj_list_sets, probj->obj_list_free_list); } l = probj->obj_list_free_list; probj->obj_list_free_list = l->next; @@ -230,28 +247,22 @@ list_remove (probj_t *probj, obj_list **list) } } -typedef struct class_tree { - pr_class_t *class; - obj_list *subclasses; -} class_tree; - -class_tree *class_tree_free_list; - static class_tree * -class_tree_new (void) +class_tree_new (probj_t *probj) { int i; class_tree *t; - if (!class_tree_free_list) { - class_tree_free_list = calloc (128, sizeof (class_tree)); + if (!probj->class_tree_free_list) { + probj->class_tree_free_list = calloc (128, sizeof (class_tree)); for (i = 0; i < 127; i++) { - class_tree *x = &class_tree_free_list[i]; + class_tree *x = &probj->class_tree_free_list[i]; x->subclasses = (obj_list *) (x + 1); } + DARRAY_APPEND (&probj->class_tree_sets, probj->class_tree_free_list); } - t = class_tree_free_list; - class_tree_free_list = (class_tree *) t->subclasses; + t = probj->class_tree_free_list; + probj->class_tree_free_list = (class_tree *) t->subclasses; t->subclasses = 0; return t; } @@ -282,10 +293,10 @@ create_tree_of_subclasses_inherited_from (probj_t *probj, pr_class_t *bottom, superclass = bottom->super_class ? Hash_Find (probj->classes, super_class) : 0; - tree = prev = class_tree_new (); + tree = prev = class_tree_new (probj); prev->class = bottom; while (superclass != upper) { - tree = class_tree_new (); + tree = class_tree_new (probj); tree->class = superclass; tree->subclasses = list_cons (probj, prev, tree->subclasses); super_class = PR_GetString (pr, superclass->super_class); @@ -320,7 +331,7 @@ _obj_tree_insert_class (probj_t *probj, class_tree *tree, pr_class_t *class) return tree; list = list->next; } - node = class_tree_new (); + node = class_tree_new (probj); node->class = class; tree->subclasses = list_cons (probj, node, tree->subclasses); return tree; @@ -381,8 +392,8 @@ obj_create_classes_tree (probj_t *probj, pr_module_t *module) static void obj_destroy_class_tree_node (probj_t *probj, class_tree *tree, int level) { - tree->subclasses = (obj_list *) class_tree_free_list; - class_tree_free_list = tree; + tree->subclasses = (obj_list *) probj->class_tree_free_list; + probj->class_tree_free_list = tree; } static void @@ -1414,6 +1425,18 @@ rua_obj_error (progs_t *pr, void *data) int count = pr->pr_argc - 3; pr_type_t **args = &pr->pr_params[3]; + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 3); + count = va_list->count; + if (count) { + args = alloca (count * sizeof (pr_type_t *)); + for (int i = 0; i < count; i++) { + args[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + args = 0; + } + } obj_verror (probj, object, code, fmt, count, args); } @@ -2068,6 +2091,18 @@ rua__i_Object_error_error_ (progs_t *pr, void *data) int count = pr->pr_argc - 3; pr_type_t **args = &pr->pr_params[3]; + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 3); + count = va_list->count; + if (count) { + args = alloca (count * sizeof (pr_type_t *)); + for (int i = 0; i < count; i++) { + args[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + args = 0; + } + } dsprintf (probj->msg, "error: %s (%s)\n%s", PR_GetString (pr, object_get_class_name (probj, self)), object_is_instance (probj, self) ? "instance" : "class", fmt); @@ -2336,10 +2371,16 @@ rua_obj_destroy (progs_t *pr, void *_res) free (probj->selector_sels); free (probj->selector_names); free (probj->selector_argc); - //FIXME free (probj->obj_list_free_list); - //FIXME free (class_tree_free_list); - //FIXME class_tree_free_list = 0; + for (size_t i = 0; i < probj->obj_list_sets.size; i++) { + free (probj->obj_list_sets.a[i]); + } + DARRAY_CLEAR (&probj->obj_list_sets); + + for (size_t i = 0; i < probj->class_tree_sets.size; i++) { + free (probj->class_tree_sets.a[i]); + } + DARRAY_CLEAR (&probj->class_tree_sets); PR_RESDELMAP (probj->dtables); @@ -2358,9 +2399,11 @@ RUA_Obj_Init (progs_t *pr, int secure) probj->protocols = Hash_NewTable (1021, protocol_get_key, 0, probj, pr->hashctx); probj->load_methods = Hash_NewTable (1021, 0, 0, probj, pr->hashctx); - probj->msg = dstring_newstr(); Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, load_methods_compare); + probj->msg = dstring_newstr(); + DARRAY_INIT (&probj->obj_list_sets, 32); + DARRAY_INIT (&probj->class_tree_sets, 32); PR_Sprintf_SetAtHandler (pr, rua_at_handler, probj); diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 384c3bfea..e0a8a023a 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -657,7 +657,10 @@ bi_scene_clear (progs_t *pr, void *_res) static void bi_scene_destroy (progs_t *pr, void *_res) { - free (_res); + rua_scene_resources_t *res = _res; + PR_RESDELMAP (res->scene_map); + PR_RESDELMAP (res->lighting_map); + free (res); } void diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 090141414..a0c291d79 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -480,6 +480,12 @@ main (int argc, char **argv) ret = thread_data.a[main_ind]->return_code; } + for (size_t i = 0; i < thread_data.size; i++) { + qwaq_thread_t *thread = thread_data.a[i]; + DARRAY_CLEAR (&thread->args); + free (thread_data.a[i]); + } + DARRAY_CLEAR (&thread_data); Cbuf_Delete (qwaq_cbuf); Sys_Shutdown (); return ret;