From 43ab25f007ba2a29d7c0fda694d6831aafad33a0 Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Tue, 19 Nov 2024 15:34:11 +0100 Subject: [PATCH] MINOR: hlua_fcn: wrap pat_ref struct for patref class In order to extend the patref class features, let's wrap the pat_ref struct into hlua_patref struct. This way we may add additional data alongside the pat_ref pointer to store additional context required for pat_ref data manipulation from lua. Since the wrapper (hlua_patref) is an allocated object, we declare the _gc metamethod for patref class in order to properly cleanup resources when they are out of scope. --- include/haproxy/hlua-t.h | 7 +++++- src/hlua_fcn.c | 53 ++++++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/include/haproxy/hlua-t.h b/include/haproxy/hlua-t.h index 80598f9e9..0d9abd550 100644 --- a/include/haproxy/hlua-t.h +++ b/include/haproxy/hlua-t.h @@ -234,8 +234,13 @@ struct hlua_server_list_iterator_context { struct proxy *px; }; +/* pat_ref struct wrapper for lua */ +struct hlua_patref { + struct pat_ref *ptr; +}; + struct hlua_patref_iterator_context { - struct pat_ref *ref; + struct hlua_patref *ref; struct bref bref; /* back-reference from the pat_ref_elt being accessed * during listing */ }; diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c index 315b2dd2e..02b82c5a9 100644 --- a/src/hlua_fcn.c +++ b/src/hlua_fcn.c @@ -2620,28 +2620,31 @@ static int hlua_regex_free(struct lua_State *L) int hlua_patref_get_name(lua_State *L) { - struct pat_ref *ref; + struct hlua_patref *ref; + ref = hlua_checkudata(L, 1, class_patref_ref); BUG_ON(!ref); - lua_pushstring(L, ref->reference); + lua_pushstring(L, ref->ptr->reference); return 1; } int hlua_patref_is_map(lua_State *L) { - struct pat_ref *ref; + struct hlua_patref *ref; ref = hlua_checkudata(L, 1, class_patref_ref); BUG_ON(!ref); - lua_pushboolean(L, !!(ref->flags & PAT_REF_MAP)); + lua_pushboolean(L, !!(ref->ptr->flags & PAT_REF_MAP)); return 1; } void hlua_fcn_new_patref(lua_State *L, struct pat_ref *ref) { + struct hlua_patref *_ref; + lua_newtable(L); /* Pop a class patref metatable and affect it to the userdata @@ -2651,7 +2654,12 @@ void hlua_fcn_new_patref(lua_State *L, struct pat_ref *ref) lua_setmetatable(L, -2); if (ref) { - lua_pushlightuserdata(L, ref); + /* allocate hlua_patref wrapper and store it in the metatable */ + _ref = malloc(sizeof(*_ref)); + if (!_ref) + luaL_error(L, "Lua out of memory error."); + _ref->ptr = ref; + lua_pushlightuserdata(L, _ref); lua_rawseti(L, -2, 0); } @@ -2660,6 +2668,14 @@ void hlua_fcn_new_patref(lua_State *L, struct pat_ref *ref) hlua_class_function(L, "is_map", hlua_patref_is_map); } +int hlua_patref_gc(lua_State *L) +{ + struct hlua_patref *ref = hlua_checkudata(L, 1, class_patref_ref); + + free(ref); + return 0; +} + int hlua_listable_patref_newindex(lua_State *L) { /* not yet supported */ return 0; @@ -2671,7 +2687,7 @@ int hlua_listable_patref_newindex(lua_State *L) { */ int hlua_listable_patref_index(lua_State *L) { - struct pat_ref *ref; + struct hlua_patref *ref; const char *key; struct pat_ref_elt *elt; @@ -2679,10 +2695,10 @@ int hlua_listable_patref_index(lua_State *L) key = luaL_checkstring(L, 2); /* Perform pat ref element lookup by key */ - HA_RWLOCK_WRLOCK(PATREF_LOCK, &ref->lock); - elt = pat_ref_find_elt(ref, key); + HA_RWLOCK_WRLOCK(PATREF_LOCK, &ref->ptr->lock); + elt = pat_ref_find_elt(ref->ptr, key); if (elt == NULL) { - HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &ref->lock); + HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &ref->ptr->lock); lua_pushnil(L); return 1; } @@ -2691,7 +2707,7 @@ int hlua_listable_patref_index(lua_State *L) lua_pushstring(L, elt->sample); else lua_pushboolean(L, 1); // acl: just push true to tell that the key exists - HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &ref->lock); + HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &ref->ptr->lock); return 1; } @@ -2706,33 +2722,33 @@ static int _hlua_listable_patref_pairs_iterator(lua_State *L, int status, lua_KC context_index = lua_upvalueindex(1); hctx = lua_touserdata(L, context_index); - HA_RWLOCK_WRLOCK(PATREF_LOCK, &hctx->ref->lock); + HA_RWLOCK_WRLOCK(PATREF_LOCK, &hctx->ref->ptr->lock); if (LIST_ISEMPTY(&hctx->bref.users)) { /* first iteration */ - hctx->bref.ref = hctx->ref->head.n; + hctx->bref.ref = hctx->ref->ptr->head.n; } else LIST_DEL_INIT(&hctx->bref.users); // drop back ref from previous iteration next: /* reached end of list? */ - if (hctx->bref.ref == &hctx->ref->head) { - HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &hctx->ref->lock); + if (hctx->bref.ref == &hctx->ref->ptr->head) { + HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &hctx->ref->ptr->lock); lua_pushnil(L); return 1; } elt = LIST_ELEM(hctx->bref.ref, struct pat_ref_elt *, list); - if (elt->gen_id != hctx->ref->curr_gen) { + if (elt->gen_id != hctx->ref->ptr->curr_gen) { /* check if we may do something to try to prevent thread contention, * unless we run from body/init state where hlua_yieldk is no-op */ if (cnt > 10000 && hlua_gethlua(L)) { /* let's yield and wait for being called again to continue where we left off */ LIST_APPEND(&elt->back_refs, &hctx->bref.users); - HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &hctx->ref->lock); + HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &hctx->ref->ptr->lock); hlua_yieldk(L, 0, 0, _hlua_listable_patref_pairs_iterator, TICK_ETERNITY, HLUA_CTRLYIELD); // continue return 0; // not reached } @@ -2743,7 +2759,7 @@ static int _hlua_listable_patref_pairs_iterator(lua_State *L, int status, lua_KC } LIST_APPEND(&elt->back_refs, &hctx->bref.users); - HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &hctx->ref->lock); + HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &hctx->ref->ptr->lock); hctx->bref.ref = elt->list.n; @@ -2774,7 +2790,7 @@ int hlua_listable_patref_pairs_iterator(lua_State *L) int hlua_listable_patref_pairs(lua_State *L) { struct hlua_patref_iterator_context *ctx; - struct pat_ref *ref; + struct hlua_patref *ref; ref = hlua_checkudata(L, 1, class_patref_ref); @@ -2849,6 +2865,7 @@ void hlua_fcn_reg_core_fcn(lua_State *L) hlua_class_function(L, "__index", hlua_listable_patref_index); hlua_class_function(L, "__newindex", hlua_listable_patref_newindex); hlua_class_function(L, "__pairs", hlua_listable_patref_pairs); + hlua_class_function(L, "__gc", hlua_patref_gc); class_patref_ref = hlua_register_metatable(L, CLASS_PATREF); /* Create server object. */