I like Go's approach: no asserts, and only use exceptions for really exceptional stuff. (Go calls exceptions panic/recover, and tweaks the recover syntax in such a way that it's much less tempting to use it for normal error handling.)
From an outsiders perspective, with zero-knowledge, it seems like libnih should be propagating back the buffer-full error.
I agree that silently failing to reload config files in only certain circumstances could be just as bad or worse behavior than just crashing, but both behaviors seem really really bad in core system software, n'est pas?
The Go FAQ defends this decision by talking about error handling, but using assertions for error handling has always been wrong.
When events are dropped, init should manually scan the config files for changes until the event queue catches up again.
- A check that can be disabled at compile time
- A check that blows up the program if it fails
- A check that has a really convenient syntax
The "disabled at compile time" bit is pretty much insane (at least in a language with side-effects) -- you'll inevitably end up accidentally having some sort of side-effect in your asserts, and if you turn them off for your production build, you're basically inserting a whole brand-new untested configuration, running in a build that is particularly hard to debug. But probably most people just leave asserts "on" all the time. (Even if you don't have side-effects in your asserts, you're still enabling untested run-paths, which is going to give weird, hard to debug error reports.)
The second thing is blowing up the program. Sometimes, this really is all you can do, and every language has some way for this to happen -- take the head of an empty list, access beyond an array bounds, whatever.
The problem is combining it with the really convenient syntax -- it's just very tempting to assert conditions which you should actually be handling more robustly, because assert is the easiest thing to write.
I'm doing a mix of Go server-side dev and Obj-C client side dev at the moment, and I do use asserts in Obj-C land.
I try to only use them only for truly "programmer screwed up" conditions, which should all be caught during development. But we still get crashes now and then from real users from asserts that shouldn't have been asserts; we fall into temptation.
So I suspect that actually we might be better of in Obj-C land, too, avoiding asserts.
(I also like the invariant-style thinking and documentation quality of asserts, though.)
And there are languages where assertions throw a standard (i.e. catchable) exception.