49

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?

Dacav
  • 13,590
  • 11
  • 60
  • 87
  • 5
    For more than you ever wanted to know about `errno` and the C standards, see http://stackoverflow.com/questions/12945486/ – Nemo Nov 02 '12 at 14:53

6 Answers6

41

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

gbulmer
  • 4,210
  • 18
  • 20
26

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]

Community
  • 1
  • 1
Dan Moulding
  • 211,373
  • 23
  • 97
  • 98
10

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.

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
6

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:

  1. Do not return the number of bytes read, but instead have an output parameter with type int * (or size_t * or whatever you use). You can then return an error code.
  2. Assuming that your return type is a signed type and that a negative sent or received amount of bytes does not make sense, use negative values to signal the respective error conditions.
Julien Oster
  • 2,256
  • 16
  • 19
3

Yes, you can assign to it, and yes, the assignment will be thread-safe. See Is errno thread-safe?

Community
  • 1
  • 1
Kyle Jones
  • 5,492
  • 1
  • 21
  • 30
2

From: http://support.sas.com/documentation/onlinedoc/sasc/doc700/html/lr1/errno.htm

The only portable values for errno are EDOM and ERANGE

So that answers your portability question.

bluish
  • 26,356
  • 27
  • 122
  • 180
prelic
  • 4,450
  • 4
  • 36
  • 46
  • I was more interested in the technical detail of assigning it, yet I didn't expect this kind of portability issue! :) – Dacav Mar 25 '12 at 00:27
  • 1
    @Dacav - I don't think there's any special way you have to set it...you can just assign to it...I'd use the given enumeration values defined in `errno.h` if possible. – prelic Mar 25 '12 at 00:29
  • 3
    That list isn't quite complete, `EILSEQ` is mandated by the standard. – paxdiablo Mar 25 '12 at 00:32
  • 2
    @prelic My question about setting it comes from the fact that it's a thread-specific global variable implemented by using macros. +1 for the enumeration values (which of course is strictly needed if you want meaningful values!) – Dacav Mar 25 '12 at 00:32
  • @R.. As I read more, I'm seeing that...not sure if that article is outdated or just wrong. – prelic Mar 25 '12 at 00:41
  • Well POSIX is a separate standard from ISO C. It's true that ISO C doesn't define many errno values, but it does define a third one, `EILSEQ`. – R.. GitHub STOP HELPING ICE Mar 25 '12 at 01:02