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?
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.
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.
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.
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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With