6

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 but my question also applies for .

#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...
}
Community
  • 1
  • 1
oHo
  • 51,447
  • 27
  • 165
  • 200
  • Throw an exception. Don't pollute somebody else's value domain. – user207421 May 21 '15 at 10:01
  • I think that the whole idea of `errno` is to provide well-known values and mixing them with user values is wrong idea. If you want to define well-known codes for domain-specific errors, use enumeration and own values. You also break `perror`/`strerror`. – myaut May 21 '15 at 10:11
  • Thanks @EJP for your comment. But the idea is to send events to notify another object. This other object may read the `Event::err` field. Here I cannot use exceptions. Should I edit my question? – oHo May 21 '15 at 10:36
  • Thanks @myaut for your comment about [`strerror()`](http://man7.org/linux/man-pages/man3/strerror.3.html) break. Therefore my questions becomes **Is there some specific `errno` values that `strerror()` returns *"This is an user-defined error code"* ?** Is this question OK for you? – oHo May 21 '15 at 10:52
  • @olibre It typically does. But then the value of errno `x` on one implementation where it's "unknown error code" might be defined to something on aother implementation. You simply can't use `errno` to define your own errror codes. You could workaround like my answer suggests or avoid it altogether and define your own. – P.P May 21 '15 at 10:58

2 Answers2

2

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.

P.P
  • 117,907
  • 20
  • 175
  • 238
  • Thanks Blue Moon. As my code does not expose the `struct Event` outside and does not overwrite `errno`, I can use negative values in my own `Event::errnum` field :-) – oHo May 21 '15 at 11:15
0

P.P.'s answer proposes using negative value as the user-defined range. This is perfect in my case.

Below is my question snippet using the suggestion from P.P. This snippet is also available on coliru.

#include <cerrno>
#include <cstring>
#include <iostream>

#define E_MY_USER_DEFINED_ERROR -1

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 = std::strlen(name); // 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");
    std::cout << std::strerror( e.errnum ) << std::endl;
}

Output using GCC

Unknown error -1

Output using Clang

Unknown error -1
oHo
  • 51,447
  • 27
  • 165
  • 200
  • 1
    Years late, but I'd just like to point out that the internal syscall engine uses negative value returns to indicate an errno on many of the methods. Eg for read(), 0 is (often) end of file, +ve is the size successfully read, and -ve is the error code that will eventually get written to errno. So if there is any chance that these errno values could get passed through the syscall interface, eg via fusermount, then much trouble could ensue. Probably you are better setting bit 14 - high enough to not clash, but low enough to not get truncated or treated as a sign bit. – Gem Taylor Oct 03 '19 at 13:57
  • This is incorrect. In the manual page of read, write, ioctl and other system calls, it is written that -- "On error, -1 is returned, and errno is set appropriately." – Krishnendu Oct 31 '22 at 07:30