I'm writing a module which exports an interface similar to send
and recv
.
Since those functions are supposed to return respectively the number of sent and received bytes, I cannot do proper error management as I would do normally (i.e. using enumeratives and returning mnemonic values).
In a situation like this should I set errno
as the standard library does? If so, since errno
is thread specific, is there a particular way of writing on it, or can I simply assign a value to it?
Edit: experimenting it I noticed that setting errno
by assignment is working. Still: is this safe and portable for any system?
The main reason for using errno is to give more information about the error condition. This is especially useful in situations where most (or even all) possible return values of a function are actually valid return values. Consider the fopen() function, which returns a pointer to a FILE .
errno The value in errno is significant only when the return value of the call indicated an error (i.e., -1 from most system calls; -1 or NULL from most library functions); a function that succeeds is allowed to change errno. The value of errno is never set to zero by any system call or library function.
No, there is no need to reset errno before calling the function, because the contract reads: The opendir() and fdopendir() functions return a pointer to the directory stream. On error, NULL is returned, and errno is set appropriately. Test the return-value, and only look at errno when you actually have an error!
errno acts like an integer variable. A value (the error number) is stored in errno by certain library functions when they detect errors. At program startup, the value stored is zero.
This is a bit old, but errno - manual section 3 says that you can directly assign to it, even though it is a macro, and it will be thread local
Not only can you set errno
, in many cases you should set errno
. When calling some library functions you can only reliably detect an error if you first set errno
to zero. See strtol
for an example.
From the POSIX specification of strtol
:
[CX] [Option Start] The strtol() function shall not change the setting of errno if successful.
Since 0, {LONG_MIN} or {LLONG_MIN}, and {LONG_MAX} or {LLONG_MAX} are returned on error and are also valid returns on success, an application wishing to check for error situations should set errno to 0, then call strtol() or strtoll(), then check errno. [Option End]
Actually, you probably can do "proper" (as you put it) error management since you return an int
.
Just use non-negative values for the number of bytes read or written and negative values for error codes. You don't have to limit yourself to -1
:
enum myerrors {
ERR_NO_MEMORY = -1,
ERR_BAD_ARGS = -2,
ERR_CPU_EXPLODED = -3,
// and so on
};
However, setting errno
in the fashion you want is valid. The standard states that errno
expands to a modifiable lvalue, meaning you can set it. From C1x/n1425, 7.5 Errors <errno.h>
:
... and
errno
which expands to a modifiable lvalue that has type int, the value of which is set to a positive error number by several library functions.
You can just assign a value to errno
, but keep in mind that there are other ways to signal an error which, depending on your situation, may be more suitable:
int *
(or size_t *
or whatever you use). You can then return an error code.Yes, you can assign to it, and yes, the assignment will be thread-safe. See Is errno thread-safe?
From: http://support.sas.com/documentation/onlinedoc/sasc/doc700/html/lr1/errno.htm
The only portable values for
errno
areEDOM
andERANGE
So that answers your portability question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With