I've been researching the best way to implement error handling in C programs, but I just don't have enough experience yet in order to evaluate the different alternatives.
I have seen very few programs that try to mimic C++ exceptions using setjmp/longjmp, so it doesn't seem to be very popular. And I'm not sure how well a scheme like that plays with multithreaded code. One of the first Google results was this article, but I haven't read the whole thing yet: Exception Handling in C Without C++
Most libraries, including the C standard library, seem to use a combination of in-band error indicators and a global error indicator (errno). I'm not sure if it's required by the C standard that errno should be thread safe, but I've seen a couple of sources that hint that it's required by POSIX. Either way, if you want to extend the functionality of errno with your own error codes, you'll have to worry about making it thread safe and thus a portable nightmare.
This site is advocating that you shouldn't use in-band error indicators at all, and instead always have functions return error indicators only. That would make the error handling more thread safe, but on the other hand it would lead to more contrived code. For example, if you were to rewrite a simple function like strcmp this way, you would need to always create an additional value to hold the result.
Another question is if functions should always do as much error checking as they can, or leave some of it to the caller. For example, should the caller or function check if a parameter is a null pointer or not (in those cases when it's not allowed to be NULL)?