有关lua返回userdata致使内存不回收的问题

222 views
Skip to first unread message

齐健

unread,
Jun 6, 2016, 10:41:13 PM6/6/16
to openresty
     最近在使用openresty,添加第三方的lua模块(luagd)时,发现:若将结构体按照userdata返回给lua,即使定义userdata时,同时指定了他的__gc回收函数,那么他也没有回收,内存会持续增长。当在lua中主动调用他的回收函数,那么内存将会释放!
     包括使用client9/libinjection的lua模块,自己编译的libmodsecurity等模块,也是一样的状况!
     请问__gc为何没生效,还是说我的使用有问题?

附:
    luagd.c

    luaL_newmetatable(L, GD_IMAGE_PTR_TYPENAME);
    lua_pushliteral(L, "__index");
    lua_pushvalue(L, -3);
    lua_settable(L, -3);
    luaL_openlib(L, NULL, LgdMetatable, 0);
    lua_pop(L, 1);
    
   其中LgdMetatable如下:
   static const luaL_reg LgdMetatable[] =
  {
      { "__gc", LgdImageDestroy },
      { NULL, NULL }
  };

  LgdImageDestroy如下:
  static int LgdImageDestroy(lua_State *L) {
      gdImagePtr im = getImagePtr(L, 1);
      if (im)
          gdImageDestroy(im);
      return 0;
  }

DeJiang Zhu

unread,
Jun 11, 2016, 9:27:55 AM6/11/16
to open...@googlegroups.com
Hello,

我想应该是你用错了,userdata 是 Lua gc 自动回收的,__gc 这个元方法只是让 userdata 在释放之前,先执行这个 gc 方法

你的内存持续增长,应该是你申请的 userdata 一直在被引用,你应该修正对应的逻辑


--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com
归档: http://groups.google.com/group/openresty
官网: http://openresty.org/
仓库: https://github.com/agentzh/ngx_openresty
教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html

Miracle

unread,
Jun 13, 2016, 10:47:57 PM6/13/16
to openresty
Hello,

背景:
luagd是github上下载的代码
编译后生成gd.so

上传图片内容为body
真实图片类型为typ
每次在access_by_lua阶段调用

local im    = nil
local data = nil

if typ == "png" then
    im = gd.createFromPngStr(data)
    if im then
        data = gd.pngStr(im)
    end
end

-----------------
以上代码就结束了,得到了重构后的data,类型为string
后面代码是对data进行处理,与im无关
-----------------
如此,每次上传图片均会增大内存,很久都不释放
若手动调用if im then im:destroy() end,则立即释放
ps:源码中__gc调用destroy(),我调用时,需注释掉__gc,并放开destroy()
-----------------
难道最后需要im = nil吗?即使如此,问题依旧!

Miracle

unread,
Jun 13, 2016, 10:52:51 PM6/13/16
to openresty
刚刚代码中的gd是
       local gd = require "gd"
    得到的 

Yichun Zhang (agentzh)

unread,
Jun 22, 2016, 1:25:25 AM6/22/16
to openresty
Hello!

2016-06-13 19:47 GMT-07:00 Miracle:
> 背景:
> luagd是github上下载的代码
> 编译后生成gd.so
>
> 上传图片内容为body
> 真实图片类型为typ
> 每次在access_by_lua阶段调用
>
> local im = nil
> local data = nil
>
> if typ == "png" then
> im = gd.createFromPngStr(data)
> if im then
> data = gd.pngStr(im)
> end
> end
>
> -----------------
> 以上代码就结束了,得到了重构后的data,类型为string
> 后面代码是对data进行处理,与im无关
> -----------------
> 如此,每次上传图片均会增大内存,很久都不释放

看起来应当是你用的那个 luagd
库的内存泄漏问题。如果你自己不能调试和分析的话,最简单的做法便是尝试联系这个库的作者或维护者了。抱歉,我并没有时间帮你去仔细调试和分析
luagd 这个库,毕竟并不是 OpenResty 维护的组件。

Regards,
-agentzh
Reply all
Reply to author
Forward
0 new messages