TCP Exception Handling


#1

Hi,

I know that Lua does not have exception handling so I’m wondering how I can handle network communication errors. E.g.

I have a Lua application that polls over TCP. I can test if there is a TCP connection before I do a TCP read or send but what happens if the connection is lost just before I do a read or just before a send?

function n.xmlpoll(msg)
	log.trace("TCP",'INFO',"TX:"..msg)		
  
	local err = tcp:send(msg);                --- line 74

	if (err == nil) then
		print ("Tcp connect issue")
		return nil
  	end

I got this error:

Jul  7 13:26:50 notice AAF: Fri Jul  7 13:26:50 2017 SCHED-ERROR: In thread: 0x23768: ./tcpc.lua:74: attempt to index upvalue 'tcp' (a nil value) stack traceback:
Jul  7 13:26:50 notice AAF: 	./tcpc.lua:74: in function 'xmlpoll'

How can I protect for this. At the very least I want the whole application to restart automatically not stay dead as it did.

Thoughts and solutions very welcome.

Kind Regards,
Steve


#2

Hi,

“Lua does not have exception handling”
-> Actually there are some API meant to handle Lua errors.
If there is a function you’re calling that might produce a Lua errors you want to catch, you might want to use “copcall”.
First load it:

require"coxpcall"

Then use the new global “copcall” function, it has the same API as “pcall” function documented there:
source.sierrawireless.com/resou … 1_3/#pcall

local pcall_status, command_return1, command_return2 = copcall(cmd, cmd_param1, cmd_param2)

(Note: copcall is similar to “standard” pcall but it also handles coroutine use cases).

" can test if there is a TCP connection before"
“I got this error: /tcpc.lua:74: attempt to index upvalue ‘tcp’”
-> I would need tcp variable definition in your code to help you more on that topic.

“At the very least I want the whole application to restart automatically not stay dead as it did.”
-> If your application process ends with a system exit code different from 0, then it will be restarted.

So you may use copcall to catch errors and then call os.exit(-1) to force the restart of your application.
But in your case, the upvalue error look like something that should be able to fix in the app.

You also can use this kind of code to catch your main “thread” termination.
This is to replace/improve the default and simple “sched.loop” call that must already be in your app.

--register to 'die' to properly log exits
local mainthread = sched.run(main)
sched.sigOnce(mainthread, 'die', function(ev, status) log('MYAPP', 'INFO', 'Exiting [%d]', status and 0 or -1) os.exit(status and 0 or -1) end)
sched.loop()

Please note that this supposes that the “main” function will keep running until an error happens.
So if you also use copcall within the main “thread”, you might not jump into that thread termination handler very often , but it remains a good practice anyway.

Let me know if it helps you or if you need more details on any of the above solutions.

Regards,