xHasKx / luamqtt

luamqtt - Pure-lua MQTT v3.1.1 and v5.0 client
https://xhaskx.github.io/luamqtt/
MIT License
160 stars 42 forks source link

Got "table overflow" error, when running under Love #49

Closed dov closed 3 weeks ago

dov commented 4 weeks ago

While trying to run luamqtt under love2d on a small gaming console (Anbernic rg40xxv), I got the following error and stacktrace:

Error

/usr/local/share/lua/5.1/mqttprotocol.lua:415:table overflow

Traceback

[love "callbacks.lua"]:228: in function 'handler'
/usr/local/share/lua/5.1/mqttprocol.lua:415: in function 'combine'
/usr/local/share/lua/5.1/mqttprocol4.lua:99: in function '_make_packet'
/usr/local/share/lua/5.1/client.lua:760: in function 'send_connect'
/usr/local/share/lua/5.1/client.lua:672: in function 'start_connecting'
/usr/local/share/lua/5.1/client.lua:919: in function '_ioloop_iteration'
/usr/local/share/lua/5.1/ioloop.lua:113: in function 'iteration'
main.lua:44: in function 'update'
[love "callbacks.lua"]:162: in function <love "callbacks.lua"]:144> 
[C]: in function 'xpcall'

Here is my love main.lua script:

local mqtt = require("mqtt")

local client
local ioloop
local info = "Waiting for message..."

function love.load()
  print('love.load()')
  client = mqtt.client{ uri = "192.168.1.11", clean = true }
  ioloop = mqtt:get_ioloop()
  ioloop:add(client)
  print('got client')

  -- assign MQTT client event handlers
  client:on{
      connect = function(connack)
          if connack.rc ~= 0 then
              print("connection to broker failed:", connack:reason_string(), connack)
              return
          end
          print('connection established')

          -- connection established, now subscribe to test topic and publish a message after
          assert(client:subscribe{ topic="luamqtt/#", qos=1, callback=function()
              assert(client:publish{ topic = "luamqtt/simpletest", payload = "hello" })
          end})
      end,

      message = function(msg)
          assert(client:acknowledge(msg))

          -- receive one message and disconnect
          print("received message", msg)

          -- Set variable to be displayed
          info = msg.payload
  --        client:disconnect()
      end,
  }
end

function love.update(dt)
    -- Poll the MQTT client to process incoming messages
  ioloop:iteration()
end

function love.draw()
  love.graphics.print(info, 10, 10)
end

What is strange to me is that the following script, without love, works on the same platform:

-- load mqtt library
local mqtt = require("mqtt")
local socket = require("socket")

local client = mqtt.client{ uri = "192.168.1.11", clean = true }

-- assign MQTT client event handlers
client:on{
    connect = function(connack)
        if connack.rc ~= 0 then
            print("connection to broker failed:", connack:reason_string(), connack)
            return
        end
        print('connection established')

        -- connection established, now subscribe to test topic and publish a message after
        assert(client:subscribe{ topic="luamqtt/#", qos=1, callback=function()
            assert(client:publish{ topic = "luamqtt/simpletest", payload = "hello" })
        end})
    end,

    message = function(msg)
        assert(client:acknowledge(msg))

        -- receive one message and disconnect
        print("received message", msg)
--        client:disconnect()
    end,
}

function sleep(sec)
    socket.select(nil, nil, sec)
end

-- run ioloop for client
ioloop = mqtt:get_ioloop()
print('got loop')
ioloop:add(client)
while true do
--  mqtt.run_ioloop(client)
  ioloop:iteration()
  sleep(0.2)  
end  

I installed luamqtt by the command luarocks-5.1 install luamqtt, and the output from the installation was:

root@ANBERNIC:/home/dov/learning/lua# luarocks-5.1 install luamqtt
Installing https://luarocks.org/luamqtt-3.4.3-1.rockspec
Cloning into 'luamqtt'...
remote: Enumerating objects: 1482, done.
remote: Counting objects: 100% (490/490), done.
remote: Compressing objects: 100% (69/69), done.
remote: Total 1482 (delta 459), reused 421 (delta 421), pack-reused 992 (from 1)
Receiving objects: 100% (1482/1482), 316.62 KiB | 3.68 MiB/s, done.
Resolving deltas: 100% (942/942), done.
Note: switching to '579c90bb8679dcaf29ad5a0864ab18e5271a061d'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

luamqtt 3.4.3-1 depends on lua >= 5.1, <= 5.4 (5.1-1 provided by VM)
luamqtt 3.4.3-1 depends on luasocket >= 3.0rc1-2 (3.1.0-1 installed)
luamqtt 3.4.3-1 is now installed in /usr/local (license: MIT)
xHasKx commented 4 weeks ago

Hi @dov,

Does that error appears immediately (on first connect to your broker) or after some time of a proper work?

dov commented 4 weeks ago

Hi @dov,

Does that error appears immediately (on first connect to your broker) or after some time of a proper work?

It happens immediately on startup.

xHasKx commented 3 weeks ago

I suppose it's related to luajit, not to luamqtt:

When connecting, luamqtt creates relatively small tables to create a MQTT CONNECT packet, so I have no any idea how you can get an overflow error for them. Here I've added a simple traces and executed your script to see that tables:

image

Please close the issue if you have no more questions.

dov commented 3 weeks ago

@xHasKx Thanks for your reply!

It is however not clear to me the fact that if I run luajit from the command line, it works:

luajit simple-mqtt.lua

I also inserted your patch, and I get the same output as you, with the excetion that my luamqtt version is: "\0\22luamqtt-v3-4-3-cb511a8".

Do you have any idea of why luajit works in standalone mode with luamqtt, but when combined with love, it crashes?

xHasKx commented 3 weeks ago

with the excetion that my luamqtt version is: "\0\22luamqtt-v3-4-3-cb511a8".

This is because "cb511a8" is a random part generated for each client instance (if not set explicitly as id=...)

Do you have any idea of why luajit works in standalone mode with luamqtt, but when combined with love, it crashes?

Please read two links I've mentioned above. One of them shows discussion about invalid ffi usage. I suppose your love2d lib is doing the same wrong thing.

dov commented 3 weeks ago

Ok. Thanks. I'll try to fix love2d on my own.