Releasing closures

狂风中的少年 提交于 2019-12-24 08:22:40

问题


On a nodemcu, I'm using a closure to send a file over a socket, like this:

function sendfile(sock, name)
    local fd = file.open(name, "r")

    function sendchunk()
        local data = fd:read()
        if data then
            sock:send(data)
        else
            fd:close()
            sock:close()
        end
    end

    sock:on("sent", sendchunk)
    sendchunk()
end

After transferring a few files, the interpreter panics due to "not enough memory". I can imagine this may be due to closure still hanging around. It would be difficult for the garbage collector to determine that sendchunk() will not be called again once the file and socket are closed.

Unfortunately my googling has not revealed a method to end the closure and free the memory it is using.

Am I using a wrong method to do this? Should I perhaps use an anonymous function or something?


回答1:


It was already mentioned here that :on() invocation saves reference to callback closure inside Lua registry.
I guess this closure will be cleared from Lua registry inside __gc metamethod of sock object,
but sock object will not be collected if the closure references sock object.
To solve this problem you should avoid hard-coding a reference to sock upvalue in the body of sendchunk() function.
For example, exploit the fact that the first argument passed to callback function is always the socket object.

function sendfile(sock, name)
   local fd = file.open(name, "r")

   local function sendchunk(sck)
      local data = fd:read()
      if data then
         sck:send(data)
      else
         fd:close()
         sck:close()
      end
   end

   sock:on("sent", sendchunk)
   sendchunk(sock)
end


来源:https://stackoverflow.com/questions/49989331/releasing-closures

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!