I have a piece of Lua code that is sending a udp message out, that is working. However I want to make it more error proof. So I have entered a wrong dns name to provoke a resolution failure. I do not really care what in that block fails, I just want to be able to handle the error gracefully. In other languages I would use try-catch. Here I understand pcall is supposed to fill that gap. So I am trying to use pcall and am trying to pass buttonPin to the sendMessageToServer() function.
This approach is not working, nothing is caught, the whole node crashes:
if(pcall(sendMessageToServer, buttonPin))
then
ledOn(ledGreen)
print("Message sent.")
else
ledOn(ledRed)
print("Error: Message could not be sent.")
end
This approach does the opposite: It doesn't crash and looks as if everything is ok, so pcall returns true:
if(pcall(function() sendMessageToServer(buttonPin) end))
then
ledOn(ledGreen)
print("Message sent.")
else
ledOn(ledRed)
print("Error: Message could not be sent.")
end
But it should run... if I simply remove the word pcall, making the function run regularly, the crash occurs as expected.
Best regards, Jens
UPDATE: Complete code and intentionally caused error
require ("config")
require ("cryptography")
function armAllButtons()
ledOff(ledGreen)
ledOff(ledYellow)
ledOff(ledRed)
for i,v in ipairs(buttonPins)
do
--print(i,v)
armButton(v)
end
end
function armButton(buttonPin)
print("Arming pin "..buttonPin.." for button presses.")
gpio.mode(buttonPin,gpio.INT,gpio.FLOAT)
gpio.trig(buttonPin, direction, function () notifyButtonPressed(buttonPin) end)
print("Waiting for button press on "..buttonPin.."...")
end
function notifyButtonPressed(buttonPin)
--print("Button pressed. Notifiying server at "..serverIp..":"..serverPort)
-- show status
ledOn(ledYellow)
print("Button at pin "..buttonPin.." pressed.")
ledOff(ledGreen)
ledOff(ledYellow)
ledOff(ledRed)
-- show status
--if(pcall(sendMessageToServer,buttonPin))
if(sendMessageToServer(buttonPin))
then
ledOn(ledGreen)
print("Message sent.")
else
ledOn(ledRed)
print("Error: Message could not be sent.")
end
-- Rearm pin for interrupts
armButton(buttonPin)
end
function sendMessageToServer(buttonPin)
print("Notifying server at "..serverIp..":"..serverPort)
--TODO: Include some variable. The current code is vulnerable to replay attacks.
conn = net.createConnection(net.UDP, 0)
conn:connect(serverPort,serverIp)
local msg = node.chipid()..";"..buttonPin..";ButtonPressed"
local hash = getHashValue(msg..encryptionPassword)
print("Sending "..msg.." with hash "..hash.." to server "..serverIp..":"..serverPort)
conn:send(msg..';'..hash)
conn:close()
conn = nil
end
function ledOn(ledPin)
gpio.write(ledPin,gpio.HIGH)
end
function ledOff(ledPin)
gpio.write(ledPin,gpio.LOW)
end
armAllButtons()
Error when not using pcall:
dofile("button.lua")
Arming pin 5 for button presses.
Waiting for button press on 5...
Arming pin 6 for button presses.
Waiting for button press on 6...
> Button at pin 5 pressed.
Notifying server at <incorrectDnsEntry>:36740
Sending 14695197;5;ButtonPressed with hash <someHashValue> to server <incorrectDnsEntry>:36740
Error: Message could not be sent.
Arming pin 5 for button presses.
Waiting for button press on 5...
DNS retry 1!
DNS retry 2!
DNS retry 3!
DNS retry 4!
DNS Fail!
?ˆÈ)ŠâF
‘ŽF
”Œ¦ú
NodeMCU 0.9.6 build 20150704 powered by Lua 5.1.4
Arming pin 5 for button presses.
Waiting for button press on 5...
Arming pin 6 for button presses.
Waiting for button press on 6...
IP unavaiable, Waiting...
> IP unavaiable, Waiting...
IP unavaiable, Waiting...
IP unavaiable, Waiting...
IP unavaiable, Waiting...
Config done, IP is 192.168.x.x
Display with pcall used:
Config done, IP is 192.168.x.x
Button at pin 5 pressed.
Notifying server at <incorrectDnsEntry>:36740
Sending 14695197;5;ButtonPressed with hash <someHashValue> to server <incorrectDnsEntry>:36740
Message sent.
Arming pin 5 for button presses.
Waiting for button press on 5...
So I'm not manually signalling the error.
error/lua_erroror is your code using some "out-of-band" way to signal this error that lua doesn't understand?pcallcan only catch errors propagated witherror/lua_error. From what I can tell, those errors you're seeing are just being outputted to stderr. How does the API you're working with communicate errors? You need to take that and rethrow them as lua errors using the mentioned function.function () ... endand get different behavior.