I have code that parses a configuration file, which may send output to stdout or stderr in case of errors.
Unfortunately, when I pipe the output of my program to /dev/null, I get an exception: ios_base::clear: unspecified iostream_category error
with stderror Inappropriate ioctl for device
.
Here is the relevant part of my code:
try {
file.exceptions(std::ios::failbit | std::ios::badbit);
file.open(config_file);
// file.exceptions(std::ios::failbit);
}
catch (std::ios_base::failure& e) {
throw std::invalid_argument(std::string("Can't open config file ") + config_file + ": " + strerror(errno));
}
try {
errno = 0; // reset errno before I/O operation.
// ...
while (std::getline(file, line)) {
if ( [... unknown line ...] ) {
std::cerr << "Invalid line in config " << config_file << ": " << line << std::endl;
continue;
}
// debug info to STDOUT:
std::cout << config_file << ": " << line << std::endl;
}
} catch (std::ios_base::failure& err) {
std::cout << "Caught exception " << err.what() << std::endl;
if (errno != 0) {
char* theerror = strerror(errno);
file.close();
throw std::invalid_argument(std::string("Can't read config file ") + config_file + ": " + theerror);
}
}
try {
file.close();
}
catch (std::ios_base::failure& e) {
throw std::invalid_argument(std::string("Can't close config file ") + config_file + ": " + strerror(errno));
}
Here is an example of an exception:
~> ./Application test1.conf > /dev/null
test1.conf: # this is a line in the config file
Caught exception ios_base::clear: unspecified iostream_category error
When I don't pipe to /dev/null
(but to stdout or a regular file), all is fine. I first suspected that the cout and cerr where causing problems, but I'm not sure.
I finally found that I could resolve this by enabling this line after opening the file, so that the badbit-type of exceptions are ignored.
file.exceptions(std::ios::failbit);
Frankly, I'm too novice in C++ to understand what is going on here.
My questions: what is causing the unspecified iostream_category
exception? How can I avoid it? Is setting file.exceptions(std::ios::failbit);
indeed a proper solution, or does that give other pitfalls? (A pointer to a good source detailing best practices for opening files in C++, which does included all proper exception handling, or some background explained, is highly appreciated!)