Home > database >  Alternatives to using what() for exception details in boost
Alternatives to using what() for exception details in boost

Time:10-05

I am using the following C code from the boost library :

try{

child c(commandString, (std_out & std_err) > pipe_stream);

} catch(process_error &pe){
    cout<<pe.what()<<" second line"<<endl;

}

The commandString is a command like ls or any other command. But if a command that does not exist is typed as per the documentation it throws the process_error exception.
I am catching the exception here but not sure if there is a better way to print out the details of the exception or error than pe.what() above?

CodePudding user response:

If you look at the boost reference about boost::process::process_error, you can read this:

struct process_error : public system_error {
};

It merely inherits std::system_error but can then be distinguished in the catch-block from other system errors.

emphasis mine

If you look then at the std::system_error reference, like all other standard exceptions, what() is the way to provide detailed information about the raised error so I would say yes, this is the proper way to print out the exception details.

But since boost::process::process_error does not override the what() function, it would return the same as a std::system_error would.

CodePudding user response:

An alternative interface is using std::error_code.

There are pros and cons:

  • PRO: it enables you to get more detail about where an error condition arose. (This is a hypothetical difference because it's not specified whether what() may include info beyond an error condition)

  • CON: it might not get as much detail as in the exception message

  • CON: since some errors are exceptional, it's harder to express the possible error conditions in the interface: the error conditions get in the way in a way that exceptions do not

    in your code you might have created this problem by handling exceptions: now how do decide what value(s) to return

  • NEUTRAL: you may still have to handle exceptions because exceptions can arise from any related code (e.g. during setup, doing allocations).

  • NEUTRAL: the code() member of boost::process::process_error is likely to be 100% identical to the error_code that you get

Demo

Contrast the implementations and output below:

Live On Coliru

#include <boost/process.hpp>
#include <iostream>
namespace bp = boost::process;

int using_exceptions(std::string const& commandString) {
    try {
        bp::pstream pipe_stream;
        bp::child   c(commandString, (bp::std_out & bp::std_err) > pipe_stream);
        c.wait();
        return c.exit_code();
    } catch (std::exception const& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
        return -1; // WHAT TO RETURN
    }
}

int using_error_code(std::string const& commandString) {
    try {
        bp::pstream pipe_stream;
        std::error_code ec;

        bp::child c(commandString, (bp::std_out & bp::std_err) > pipe_stream,
                    ec);

        if (ec) {
            std::cerr << "Cannot spawn child process: " << ec.message() << "\n";
            return -1; // WHAT TO RETURN?
        } else {
            c.wait(ec);
            std::cerr << "Error: " << ec.message() << "\n";
            return c.exit_code();
        }

    } catch (std::exception const& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
        return -1; // WHAT TO RETURN
    }
}

int main()
{
    auto cmd = "/usr/bin/bogus";
    std::cout << "Using error_code: " << using_error_code(cmd) << "\n";
    std::cout << "Using exceptions: " << using_exceptions(cmd) << "\n";
}

Prints

Using error_code: Cannot spawn child process: No such file or directory
-1
Using exceptions: Exception: execve failed: No such file or directory
-1
  • Related