]> source.dussan.org Git - rspamd.git/commitdiff
Rework lua_regexp lifetime.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 9 Apr 2015 10:50:59 +0000 (11:50 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 9 Apr 2015 10:50:59 +0000 (11:50 +0100)
src/lua/lua_common.c
src/lua/lua_common.h
src/lua/lua_regexp.c
src/plugins/lua/settings.lua

index 0364dff665a6ad62c0c4adb3139d097d4ab9e134..1077fd00e0aeb1a2b3cfac79ff87fc3413e602cd 100644 (file)
@@ -221,7 +221,7 @@ rspamd_lua_init (struct rspamd_config *cfg)
        luaopen_url (L);
        luaopen_classifier (L);
        luaopen_statfile (L);
-       luaopen_glib_regexp (L);
+       luaopen_regexp (L);
        luaopen_cdb (L);
        luaopen_xmlrpc (L);
        luaopen_http (L);
index 9299bd6510e3db06329acd6abb9f39b2e9411eb8..cb53c05f2248ff187dd2ad7df68e94e3e600cf43 100644 (file)
@@ -182,7 +182,7 @@ void luaopen_image (lua_State *L);
 void luaopen_url (lua_State *L);
 void luaopen_classifier (lua_State *L);
 void luaopen_statfile (lua_State * L);
-void luaopen_glib_regexp (lua_State *L);
+void luaopen_regexp (lua_State *L);
 void luaopen_cdb (lua_State *L);
 void luaopen_xmlrpc (lua_State * L);
 void luaopen_http (lua_State * L);
index fa7389537416824c69f8ea1c522ad43835ae1eec..a384e36cc8cb4995dfc7e7d6e66ac3d4986d7dab 100644 (file)
  * @example
  * local rspamd_regexp = require "rspamd_regexp"
  *
- * local re = rspamd_regexp.create_cached('/^\\s*some_string\\s*^/i')
+ * local re = rspamd_regexp.create_cached('/^\\s*some_string\\s*$/i')
  * re:match('some_string')
- * -- Required since regexp are optimized to be stored in the cache
- * re:destroy()
- *
- * -- Or it is possible to use metatable if re is an element of some table
- * local tbl = {}
- * tbl['key'] = rspamd_regexp.create_cached('.*')
- * setmetatable(tbl, {
- *     __gc = function(t) t:destroy() end
- * })
+ * local re = rspamd_regexp.create_cached('/\\s+/i')
+ * re:split('word word   word') -- returns ['word', 'word', 'word']
  */
 
 LUA_FUNCTION_DEF (regexp, create);
@@ -52,6 +45,7 @@ LUA_FUNCTION_DEF (regexp, search);
 LUA_FUNCTION_DEF (regexp, match);
 LUA_FUNCTION_DEF (regexp, split);
 LUA_FUNCTION_DEF (regexp, destroy);
+LUA_FUNCTION_DEF (regexp, gc);
 
 static const struct luaL_reg regexplib_m[] = {
        LUA_INTERFACE_DEF (regexp, get_pattern),
@@ -60,6 +54,7 @@ static const struct luaL_reg regexplib_m[] = {
        LUA_INTERFACE_DEF (regexp, split),
        LUA_INTERFACE_DEF (regexp, destroy),
        {"__tostring", lua_regexp_get_pattern},
+       {"__gc", lua_regexp_gc},
        {NULL, NULL}
 };
 static const struct luaL_reg regexplib_f[] = {
@@ -69,6 +64,9 @@ static const struct luaL_reg regexplib_f[] = {
        {NULL, NULL}
 };
 
+#define LUA_REGEXP_FLAG_DESTROYED (1 << 0)
+#define IS_DESTROYED(re) ((re)->re_flags & LUA_REGEXP_FLAG_DESTROYED)
+
 rspamd_mempool_t *regexp_static_pool = NULL;
 
 struct rspamd_lua_regexp {
@@ -119,7 +117,7 @@ lua_regexp_create (lua_State *L)
                g_error_free (err);
        }
        else {
-               new = g_slice_alloc (sizeof (struct rspamd_lua_regexp));
+               new = g_slice_alloc0 (sizeof (struct rspamd_lua_regexp));
                new->re = re;
                pnew = lua_newuserdata (L, sizeof (struct rspamd_lua_regexp *));
                rspamd_lua_setclass (L, "rspamd{regexp}", -1);
@@ -147,7 +145,7 @@ lua_regexp_get_cached (lua_State *L)
        line = luaL_checkstring (L, 1);
        re = rspamd_regexp_cache_query (NULL, line, NULL);
        if (re) {
-               new = g_slice_alloc (sizeof (struct rspamd_lua_regexp));
+               new = g_slice_alloc0 (sizeof (struct rspamd_lua_regexp));
                new->re = re;
                pnew = lua_newuserdata (L, sizeof (struct rspamd_lua_regexp *));
                rspamd_lua_setclass (L, "rspamd{regexp}", -1);
@@ -185,7 +183,7 @@ lua_regexp_create_cached (lua_State *L)
        line = luaL_checkstring (L, 1);
        re = rspamd_regexp_cache_query (NULL, line, NULL);
        if (re) {
-               new = g_slice_alloc (sizeof (struct rspamd_lua_regexp));
+               new = g_slice_alloc0 (sizeof (struct rspamd_lua_regexp));
                new->re = re;
                pnew = lua_newuserdata (L, sizeof (struct rspamd_lua_regexp *));
 
@@ -209,7 +207,7 @@ lua_regexp_get_pattern (lua_State *L)
 {
        struct rspamd_lua_regexp *re = lua_check_regexp (L);
 
-       if (re && re->re) {
+       if (re && re->re && !IS_DESTROYED (re)) {
                lua_pushstring (L, rspamd_regexp_get_pattern (re->re));
        }
        else {
@@ -244,7 +242,7 @@ lua_regexp_search (lua_State *L)
        gsize len;
        gboolean matched = FALSE;
 
-       if (re) {
+       if (re && !IS_DESTROYED (re)) {
                data = luaL_checklstring (L, 2, &len);
                if (data) {
                        lua_newtable (L);
@@ -290,7 +288,7 @@ lua_regexp_match (lua_State *L)
        gsize len = 0;
        gboolean raw = FALSE;
 
-       if (re) {
+       if (re && !IS_DESTROYED (re)) {
                if (lua_type (L, 2) == LUA_TSTRING) {
                        data = luaL_checklstring (L, 2, &len);
                }
@@ -343,7 +341,7 @@ lua_regexp_split (lua_State *L)
        const gchar *start = NULL, *end = NULL, *old_start;
        gint i;
 
-       if (re) {
+       if (re && !IS_DESTROYED (re)) {
                data = luaL_checklstring (L, 2, &len);
                if (data) {
                        lua_newtable (L);
@@ -371,9 +369,7 @@ lua_regexp_split (lua_State *L)
 
 /***
  * @method re:destroy()
- * We are not using `__gc` meta-method as it is usually good idea to have
- * compiled regexps to be stored permanently, so this method can be used
- * for avoiding memory leaks for temporary regexps
+ * Destroy regexp from caches if needed (the pointer is removed by garbadge collector)
  */
 static gint
 lua_regexp_destroy (lua_State *L)
@@ -383,7 +379,24 @@ lua_regexp_destroy (lua_State *L)
        if (to_del) {
                rspamd_regexp_cache_remove (NULL, to_del->re);
                rspamd_regexp_unref (to_del->re);
-               g_slice_free1 (sizeof (struct rspamd_lua_regexp), to_del);
+               to_del->re = NULL;
+               to_del->re_flags |= LUA_REGEXP_FLAG_DESTROYED;
+       }
+
+       return 0;
+}
+
+static gint
+lua_regexp_gc (lua_State *L)
+{
+       struct rspamd_lua_regexp *to_del = lua_check_regexp (L);
+
+       if (to_del) {
+               if (!IS_DESTROYED (to_del)) {
+                       rspamd_regexp_unref (to_del->re);
+               }
+
+               g_slice_free1 (sizeof (*to_del), to_del);
        }
 
        return 0;
@@ -399,7 +412,7 @@ lua_load_regexp (lua_State * L)
 }
 
 void
-luaopen_glib_regexp (lua_State * L)
+luaopen_regexp (lua_State * L)
 {
        luaL_newmetatable (L, "rspamd{regexp}");
        lua_pushstring (L, "__index");
index 92a6759e2ae9470131c365ad320a17dcce49fdc2..4b984a07e7d60f1fffae227397768cadae3b4e41 100644 (file)
@@ -291,9 +291,6 @@ local function process_settings_table(tbl)
           local re = rspamd_regexp.create(addr)
           if re then
             out['regexp'] = re
-            setmetatable(out, {
-              __gc = function(t) t['regexp']:destroy() end
-            })
           else
             rspamd_logger.err("bad regexp: " .. addr)
             return nil