Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

User-defined errno range values (POSIX or Linux-specific)

Questions for POSIX if possible, else for Linux-specific platforms:

  1. Is there user-defined errno values? (as for signals SIGUSR1 and SIGUSR2)
  2. How to find an errno value not used by the system? (negative values?)
  3. How to prevent strerror() break? (check before the errnum sign?)

My code open() a resource and notifies another object. The notification Event conveys the system errno if a failure occurs (zero on success).

But failures can also be detected in my code, e.g. if(count>=size). And I want to reuse the field Event::errnum to convey this failure. Therefore my user-defined failure code should not overlap system-defined errno values.

I have found errno range 9000–11000 reserved for user, but this seems to be specific to Transaction Processing Facility...

Note my question is not about library-defined errno. The struct Event is not exposed outside my code. My code does not overwrite errno.

Below snippet is in c++ but my question also applies for c.

#include <cerrno>

#define E_MY_USER_DEFINED_ERROR 9999

struct Event
{
    int fd;
    int errnum;
};

struct Foo
{
    Foo( int sz ) : count(0), size(sz) {}

    Event open( const char name[] )
    {
        if( count >= size )
            return { -1, E_MY_USER_DEFINED_ERROR };

        int fd = 1; // TODO: open ressource...
        if (fd < 0) return { -1, errno };
        else        return { fd, 0 };
    }

    int count, size;
};

int main()
{
    Foo bar(0);
    Event e = bar.open("my-ressource");
    // send Event to another object...
}
like image 565
oHo Avatar asked May 21 '15 09:05

oHo


1 Answers

The actual errno values are not defined by the C and C++ standards. So there's no way to return a particular (positive) integer and guarantee it to not clash with the one that an implementation uses. The C standard requires only three marco:

C11 draft, 7.5 Errors

The macros are

EDOM
EILSEQ
ERANGE

which expand to integer constant expressions with type int, distinct positive values, and which are suitable for use in #if preprocessing directives;

So you don't know what other errno values are defined in your implementation.

The errno values are postive integers in standard C and POSIX. So you could use your own enumaration with negative values to define your own error numbers. But then you can't use the strerror/perror interfaces. So you may need additional wrapper for strerror/perror to interpret your own error numbers.

Something like:

enum myErrors{
ERR1 = -1,
ERR2 = -2,
...
ERR64 = -64
};

char *my_strerror(int e)
{
   if (e>=ERR1 && e<=ERR2)
      return decode_myerror(e); // decode_myerror can have a map for  
                                //your error numbers and return string representing 'e'.
   else
      return strerror(e);
}

and a similar one for perror.

Note you should also set errno to 0 before calling your "open-resource" to make sure the errno was indeed set by your function.

I'd avoid the standard errno altogether in situations like this and define my own enumeration for errors. You could do that if your "open-resource" is not too complicated and returns too possible error codes.

like image 92
P.P Avatar answered Oct 08 '22 10:10

P.P