6

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:

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?

Guillaume Papin
  • 1,370
  • 11
  • 16

1 Answers1

6

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.

Niall Douglas
  • 9,212
  • 2
  • 44
  • 54
  • Wow thanks! I actually looked searched if this was a GCC bug, but I did not find it. Sadly I'm a bit stuck with a slightly older GCC version, so I will have to workaround this in the meantime, by using the generic_category(). – Guillaume Papin Sep 19 '18 at 09:10