I think hard exceptions (like failed asserts in C) are fine for things that are obviously programmer error (like wrong number or types of arguments). in C these are caught by the compiler, but we don't have strict type checking in candor. We need some sort of hard assert for this. I could build it into the
candor.io library and implement it in C++. It would be nice if I had a way to get the stack trace, or at least the line that threw the assert.
But the other class of errors that you don't want crashing your server are invalid user input. The way libuv (The C library behind nodejs and
candor.io) handles these errors is to return a non-zero status on any function call that potentially can throw an error. For async functions, there is a status property in the callback. It's the responsibility of the programmer to check for this status code and them pull the actual error message out of libuv using the error API.
I've done something like this for
candor.io. It's not pretty, but seems to work ok. The only sticky point is sync functions that return a value. Where do I put the status code? In lua this is done with multiple return values, but I don't think that's a feature we want to add to candor (as much as I love it).
throw = (err) {
global.prettyPrint(err)
global.exit()
}
// Used to emit on errors when libuv badness happens
check = (status) {
if (status) {
throw(require('uv').lastError())
}
}
ServerPrototype = {}
ServerPrototype.listen = (self, port, host, callback) {
if (!host) host = "0.0.0.0"
check(self.socket:bind(host, port))
check(self.socket:listen(128, (status) {
check(status)
client = new ClientPrototype
socket = Tcp.create()
client.socket = socket
check(self.socket:accept(socket))
self.onConnection(client)
check(socket:readStart((nread, chunk) {
if (nread == -1) {
err = require('uv').lastError()
client.onEnd()
} else {
throw(err)
}
return
}
if (nread > 0) {
client.onData(chunk)
return
}
}))
}))
}