Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error_code: how to set and check errno

I'm trying to understand what category I should use, when calling a C function that sets errno on Linux.

I'm not sure all the possible error codes are defined by POSIX, so I'm tempted to use the system_category.

But I like to handle generic condition in my code later on, so I would like to do things like that:

std::error_code ec;
some_func(some_path, ec);

if (ec) {
  if (ec == std::errc::file_exists) {
    // special handling
  }
  return ec;
}

To set the error code in some_func(), I expected to proceed like this:

ec.assign(EEXIST, std::system_category());

Mostly based on this discussion:

  • <system_error> categories and standard/system error codes
  • And the code sample provided by @niall-douglas:
std::error_code ec;
if(-1 == open(...))
  ec = std::error_code(errno, std::system_category());
// To test using portable code
if(ec == std::errc::no_such_file_or_directory)
   ...
// To convert into nearest portable error condition (lossy, may fail)
std::error_condition ec2(ec.default_error_condition())

-- https://stackoverflow.com/a/40063005/951426

However, on Linux, with GCC 6.1.1, I have:

  • std::error_code(EEXIST, std::system_category()) == std::errc::file_exists returns false
  • std::error_code(EEXIST, std::generic_category()) == std::errc::file_exists returns true

I was expecting the errno + system_category to be comparable with std::errc conditions.

This means my initial code that checks if (ec == std::errc::file_exists) does not work if I don't use the generic category.

Is this the expected behavior?

like image 732
Guillaume Papin Avatar asked Sep 18 '18 10:09

Guillaume Papin


People also ask

How do you check errno?

Viewing and Printing the Errno Value Your program can use the strerror() and perror() functions to print the value of errno. The strerror() function returns a pointer to an error message string that is associated with errno. The perror() function prints a message to stderr.

Does Read set errno?

Upon successful completion, read(), pread() and readv() return a non-negative integer indicating the number of bytes actually read. Otherwise, the functions return -1 and set errno to indicate the error.

Does open set errno?

If O_EXCL and O_CREAT are set, and path names a symbolic link, open() shall fail and set errno to [EEXIST], regardless of the contents of the symbolic link. If O_EXCL is set and O_CREAT is not set, the result is undefined.

Should I set errno?

Indeed we should only check errno in the case where an error occurred. This is because if no error occurred, then it is still possible that errno will contain a non-zero value (e.g. if an error occurred during the execution of a library call but the error was recovered).


1 Answers

This is a bug recently fixed in latest GCC 6, 7 and 8 point releases. It'll work as you expect if you're on the latest point release. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60555.

like image 188
Niall Douglas Avatar answered Oct 19 '22 14:10

Niall Douglas