Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Callbacks need to be longjmp safe #23

Open
daurnimator opened this issue Feb 1, 2018 · 5 comments
Open

Callbacks need to be longjmp safe #23

daurnimator opened this issue Feb 1, 2018 · 5 comments

Comments

@daurnimator
Copy link

daurnimator commented Feb 1, 2018

Callback functions (on_connect, on_message, etc.) are called from non-lua code; which I cannot see as documented to be longjmp safe.

Lua C api functions will longjmp out on failure to the last pcall.
To fix, your lua function invocations should use lua_pcall.

Additionally, other functions such as lua_pushstring can longjmp out on memory allocation failure.

lua_pushstring(ctx->L, str);

These should also be called from inside a pcall (push a pointer on the stack instead and then inside the pcall use lua_pushstring).

@daurnimator daurnimator changed the title Callbacks need to be memory allocation failure safe Callbacks need to be longjmp safe Feb 1, 2018
@daurnimator
Copy link
Author

Callback functions (on_connect, on_message, etc.) are called from non-lua code; which I cannot see as documented to be longjmp safe.

I had a look into the libmosquitto code base, and it's evident that longjmping out is unsafe, as the cleanup code here: https://github.com/eclipse/mosquitto/blob/8025f5a29b78551e1d5e9ea13ae9dacabb6830da/lib/net_mosq.c#L1142-L1147 would get skipped (amoung other issues).

The issue in coming up with a fix is that libmosquitto doesn't provide any way to report errors from callbacks; and will immediately process the next packet.

I think this means that errors in a user's lua callback also have to be silent (as we have nowhere to report them to). Sending PR with this fix.

daurnimator added a commit to daurnimator/lua-mosquitto that referenced this issue Feb 1, 2018
Lua errors (including allocation failures) would `longjmp` out of the
callbacks, bypassing cleanup in libmosquitto.

This commit changes errors from undefined behaviour (that luckily used
to get reported) to silently discarding errors.

Closes flukso#23
@karlp
Copy link
Contributor

karlp commented Apr 11, 2018

ok, I'm of the opinion now, as I was back then, that user callbacks should not be pcalled, because, as you mention yourself, this means that errors in user code are silently discarded. See 57634bc

I strongly feel this is the domain of the user to handle properly.

@daurnimator
Copy link
Author

They must be pcalled, to do otherwise would break libmosquitto in a way that the only solution is to abort() the process.

The open question is: what to do when pcall indicates an error: my current PR does nothing (throwing the error away). Instead you may want to get it back to the caller (though libmosquitto doesn't make it easy).

@karlp
Copy link
Contributor

karlp commented Apr 12, 2018

how does this break:

function realhandler(mid, topic, payload, qos, retain)
   blah
end
mqtt:set_callback(mosq.ON_MESSAGE, function(mid, topic, payload, qos, retain)
   local ok, err = pcall(realhandler, mid, topic, payload, qos, retain)
 end)

Because you want to do an awful lot of extra C code just to throw away errors. The code above makes it absolutely user choice how to handle the errors, and correctly does the pcall.

Alternatively, you could try and just reverting 57634bc and adding an api call that provides some sort of pcall handler for the case when it fails, but that sounds like a complicated user API for no gain.

@daurnimator
Copy link
Author

Because when you call lua_pushstring (to push e.g. payload) when memory constrained, lua may longjmp out due to memory allocation failure. libmosquitto does not handle such a thing safely (and is not documented to).

daurnimator added a commit to daurnimator/lua-mosquitto that referenced this issue May 23, 2018
Lua errors (including allocation failures) would `longjmp` out of the
callbacks, bypassing cleanup in libmosquitto.

This commit changes errors from undefined behaviour (that luckily used
to get reported) to silently discarding errors.

Closes flukso#23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants