calio / lua-capnproto

Lua-capnp is a pure lua implementation of capnproto based on luajit.
BSD 2-Clause "Simplified" License
70 stars 24 forks source link

Issue On Mac running lua-capnproto #4

Closed ghost closed 9 years ago

ghost commented 9 years ago

It looks like we were getting an error sometimes when serializing with the following message.

2015/02/24 17:16:02 [error] 98107#0: *4 lua entry thread aborted: runtime error: /usr/local/share/lua/5.1/capnp.lua:221: cannot convert 'false' to 'unsigned int'

The value for this was the first value, @0, in a struct, a UINT32. I moved that to the last field in the struct and it looks like the error no longer occurs.

calio commented 9 years ago

It seems you defined @0 to be UINT32, but your data is a boolean value 'false'. Can you post your schema and you data to serialize?

ghost commented 9 years ago

The definition I had looked something like the following originally.

struct Data { propA @0 : UInt32; propB @1 : UInt8; propC @2 : UInt16; }

So sometimes, like every 75 times or so, when trying to write data fast, we got that weird error.

I noticed, in the generated binding code, if I replaced the variable used for encoding with a constant number the issue did not happen.

So far it looks like if the definition is the following that the issue stops.

struct Data { propB @0 : UInt8; propC @1 : UInt16; propA @2 : UInt32; }

I assume this is an idiosyncrasy on the Mac?

calio commented 9 years ago

@rcritt You didn't provide the data you used. It's most likely that there is something wrong with your data. If you want to serialize something like { propA = false, propB = 1, propC = 2 }, it will also trigger this error.

The error message means there is a type mismatch between the data you provided (boolean "false") and the type defined in the schema UInt32.

Please check if there is any change you data contains boolean "false" in it. Or you can provide a minimal test case that can reproduce this problem.

ghost commented 9 years ago

This problem was reproducible by another colleague on his system. The issue went away for both of us when we switched the order of the Cap'n Proto fields. He was using a Mac as well.

I checked and the value was always a number, never a boolean. The issue went away with just changing the order of the fields, so the other parts of the program were the same.

We found we saw that if we tried to trigger serializations really fast, one right after another. Sometimes we got the issue but 90% or so of the time things were fine.

calio commented 9 years ago

If you think there is nothing with your data, please provide a minimal test case that can reproduce this issue. Otherwise I can't help you. And also the result of "uname -a", "luajit -v", "capnp --version" and "capnpc-lua --version" on your system that has this problem.

ghost commented 9 years ago

I was able to reproduce this incident.

This happens no matter the order I have the first property in this test.

"uname -a" = Darwin Choicestreams-MacBook-Pro-8.local 13.4.0 Darwin Kernel Version 13.4.0: Wed Dec 17 19:05:52 PST 2014; root:xnu-2422.115.10~1/RELEASE_X86_64 x86_64

"luajit -v" = LuaJIT 2.1.0-alpha -- Copyright (C) 2005-2015 Mike Pall. http://luajit.org/

"capnp --version" = Cap'n Proto version 0.5.1

"capnpc-lua --version" = Cap'n Proto lua plugin version 0.1.1-1

My Data.capnp definition is the following. I have 2 forms I tried, hence the comments.

@0xa1ebbc98ef16083a;

struct Data {

propA @0 : UInt32;

propB @1 : UInt8;

propC @2 : UInt16;

}

struct Data { propB @0 : UInt8; propC @1 : UInt16; propA @2 : UInt32; }

The nginx.conf has the following key entries.

lua_shared_dict testData 20k; location = /dataCapTest { content_by_lua ' dataTest = require "DataTest"

          ngx.say("Value of TEST=>", dataTest.getDataValue())
          dataTest.incrementDataValue()
          ngx.say("Value Incremented")
      ';
   }

The logic for this program, DataTest.lua, has the following code.

_M = {}

local shared = ngx.shared local testData = shared.testData

local dataCoder = require "Data_capnp"

local dataParser = dataCoder.Data.parse local dataSerializer = dataCoder.Data.serialize

local mathFloor = math.floor

local initialSample = {prop_a = 98765 , prop_b = 987 , prop_c = 321} testData:set("key", dataSerializer(initialSample))

function _M.getDataValue()

local dataBinary = testData.get(testData, "key") return (dataParser(dataBinary)).prop_b end

function _M.incrementDataValue() local dataBinary = testData.get(testData, "key") local dataStruct = dataParser(dataBinary)

dataStruct.prop_b = dataStruct.prop_b + 1

local nowTime = os.time() nowTime = nowTime - mathFloor(nowTime/65536) * 65536

dataStruct.prop_c = nowTime

testData.replace(testData, "key", dataSerializer(dataStruct)) end

return _M

Here is a sample error I get with the capnp from above.

P/1.1", host: "localhost:8080" 2015/02/27 14:17:02 [error] 53546#0: 9 lua entry thread aborted: runtime error: /usr/local/share/lua/5.1/capnp.lua:221: cannot convert 'false' to 'unsigned int' stack traceback: coroutine 0: /usr/local/share/lua/5.1/capnp.lua: in function 'write_num' /usr/local/share/lua/5.1/capnp.lua:240: in function 'write_struct_field' ./src-capnp/Data_capnp.lua:119: in function 'flat_serialize' ./src-capnp/Data_capnp.lua:141: in function 'dataSerializer' ./src/DataTest.lua:33: in function 'incrementDataValue' content_by_lua(nginx.conf:83):7: in function <content_by_lua(nginx.conf:83):1>, client: 127.0.0.1, server: , request: "GET /dataCapTest HTTP/1.1", host: "localhost:8080" 2015/02/27 14:17:02 [error] 53546#0: 10 lua entry thread aborted: runtime error: /usr/local/share/lua/5.1/capnp.lua:221: cannot convert 'false' to 'unsigned int' stack traceback: coroutine 0: /usr/local/share/lua/5.1/capnp.lua: in function 'write_num' /usr/local/share/lua/5.1/capnp.lua:240: in function 'write_struct_field' ./src-capnp/Data_capnp.lua:119: in function 'flat_serialize' ./src-capnp/Data_capnp.lua:141: in function 'dataSerializer' ./src/DataTest.lua:33: in function 'incrementDataValue' content_by_lua(nginx.conf:83):7: in function <content_by_lua(nginx.conf:83):1>, client: 127.0.0.1, server: , request: "GET /dataCapTest HTTP/1.1", host: "localhost:8080"

calio commented 9 years ago

@rcritt Thanks for you test case. This maybe a bug of LuaJIT. I've sent an email to Mike http://permalink.gmane.org/gmane.comp.lang.lua.luajit/6181. Hopefully we can get this fixed soon. I'll give you an update if I hear back from Mike.

calio commented 9 years ago

@rcritt Mike has confirmed and fixed this bug. You can update your LuaJIT to the latest HEAD of v2.1 branch and this issue will be gone. If you are using OpenResty bundle, add "--with-luajit=DIR" to "configure" script and compile your nginx again.

Thanks again for reporting this issue.