Passing exceptions with a callback function - c++

To start with, I don't have access to "modern" features such as std::future and std::async. I want to perform an operation asynchronosuly. The result is given in a callback. If the operation fails with an exception, I would like to pass it as an std::optional parameter, for the handler to examine. Is this considered bad practice and dangerous?
void
doOperation(std::function<void(SomeClass*, std::optional<std::exception>)> doneHandler)
{
try
{
auto result = doStuff();
doneHandler(result, cpp17::nullopt_t);
}
catch (const std::exception& e)
{
doneHandler(nullptr, e);
}
}

Related

How to use an exception outside catch statement

I have a function that may throw an exception of a variable type, but all inheriting from std::exception:
int errorCheck(int a)
{
if(a < 0)
throw a_too_small();
if(a>10)
throw a_too_big();
return a*2;
}
I want to handle this exception using Qt's SIGNAL/SLOT mechanism.
try {
errorCheck(a);
} catch(std::exception &e) {
emit errorSignal(e);
}
If the signature of errorSignal is errorSignal(std::exception e), then the original exception object is sliced and its type is lost.
If the signature is errorSignal(std::exception &e) on the other hand, the exception e leaves the catch scope, and I believe this is not allowed.
What's the cleanest solution to handle this problem?
If using C++11 is possible, you can try to use std::exception_ptr:
try {
...
} catch (...)
std::exception_ptr except = std::current_exception();
emit signal(except);
}
Then in your slot:
void myslot(std::exception_ptr e) {
try {
if (e) {
std::rethrow_exception(e);
}
} catch (...) {
...
}
}
How about making the errorSignal function signal/slot work by reference? something like errorSignal(std::exception& e)? Do that with Qt::DirectConnection too to avoid event queuing, with something like:
connect(someWidget,SomeWidget::errorSignal&,this,MainWindow::handleError&,Qt::DirectConnection);

Calling `f()` once regardless of exceptions

My understanding may be incorrect but, reading the documentation for call_once, it appears that if multiple threads are calling it simultaneously with the same once_flag and the first thread throws an exception, one of the other threads will have its callable called (and so forth until one callable returns without throwing).
My question is, if I have multiple thread all the with the same callable and I want the callable to be called truly once regardless of an exception and I want to know about the exception, do I have no choice but to do this:
void call_really_just_once()
{
std::exception_ptr e;
std::call_once(some_once_flag_, [&]
{
try
{
may_throw();
}
catch(...)
{
e = std::current_exception();
}
});
if(e)
{
std::rethrow_exception(e);
}
}

Exception not propagating properly across threads using boost::future/boost::promise

I have the following code I have simplified:
Thread two:
boost::unique_future<void> future;
TaskPtr task(new task::ReloadConfig(future));
Listener::PushTask(task);
future.wait();
try
{
future.get();
}
catch (const cfg::ConfigError& e)
{
return cmd::Result::Okay;
}
Thread two:
try
{
cfg::UpdateShared(std::shared_ptr<cfg::Config>(new cfg::Config(configFile)));
}
catch (...) // should be cfg::ConfigError
{
promise.set_exception(boost::current_exception());
return;
}
promise.set_value();
Instead of a the Cfg::ConfigError exception or one of its derived exceptions being propogated from thread two to thread one I get the following:
terminate called after throwing an instance of
'boost::exception_detail::clone_impl'
what(): std::exception
Seems this other person had similar troubles and no answer:
https://stackoverflow.com/questions/10857834/how-to-use-boostfuture-get-to-get-user-defined-exception
I also get the following error if I try to use boost::enable_current_exception:
/usr/local/include/boost/exception/exception.hpp:419:20: error: no
matching function for call to 'std::runtime_error::runtime_error()'
I can get the code working fine without exceptions, by just returning a boolean value, but this is a compromise.
I would try to do something like that in your thread two:
catch (const cfg::ConfigError& e)
{
promise.set_exception(boost::make_exception_ptr(e));
}
Otherwise if you want that current_exception() to work you have to mess with things like:
throw boost::enable_current_exception(cfg::ConfigError("meh"));

How to avoid writing repeated code in catch blocks?

I am using QT 4.8 (C++) for desktop application project, and writing exception handling which is as follows :
void callerMethod()
{
try
{
method1();
}
catch(Exception1& e)
{
// display critcal error message
// abort application
}
catch(std::Exception& e)
{
// print exception error message
}
catch(...)
{
// print unknown exception message
}
}
void method1()
{
try
{
// some initializations
// some operations (here exceptions can occur)
// clean-up code (for successful operation i.e no exception occurred)
}
catch(Exception1& e)
{
// clean-up code
throw e;
}
catch(Exception2& e)
{
// clean-up code
throw e;
}
catch(Exception3& e)
{
// clean-up code
throw e;
}
catch(...)
{
// clean-up code
throw;
}
}
So my question do I need to write the clean-up code in every catch block?
Is there any way I can avoid writing repeated code?
NOTE:: [ In method1() ] I want to re-throw exceptions which occurred
to my caller.So I can not catch them in single catch block,
because then type information will be lost.
Method1 can be much simplified by two concepts:
RAII. Put any clean-up code into destructors, and the clean-up code will be centralized.
Use the unqualified throw, and you won't need to know about the type of exception thrown.
So, method1() should look like:
void method1()
{
// some initializations of RAII objects
// some operations (here exceptions can occur)
}
The first catch clause in callerMethod can be removed if you derive Exception1 from std::exception, since the what() method is virtual.
You should throw exceptions as low as possible and catch them as high as possible in the call chain. This automatically leads to less code duplication, and centralizes error handling. You are throwing/catching all in one place, which seems a bit ... forced.
I often do this kind of thing (especially for program-ending exceptions:
int main()
try
{
function_calls_that_may_throw();
// ...
}
catch(my_exception& e)
{
e.do_exception_stuff();
}
catch(std::exception& e)
{
std::cout << e.what();
}
catch(...)
{
std::cout << "Something bad happened.\n";
}
This is only possible for throwing exceptions you don't plan on handling better or retrying the failed operation or something.
The pro of this approach is that all/most error handling code is at the top-level of your program, and all the functions in the call chain don't have to worry one bit about this stuff, all they do is throw an exception when they feel like it.
If all your clean up code is totally identical, you can do everything in your catch (...) block:
try {
// code
} catch (...) {
// cleanup
throw;
}
If your code varies slightly, you can always call a cleanup function:
try {
// code
} catch (exc1 ex) {
cleanup(args);
// exc1 specific
throw;
} catch (exc2 ex) {
cleanup(args);
// exc2 specific
throw;
} catch (...) {
cleanup(args);
throw;
}

Dispatching exceptions in C++

How should exceptions be dispatched so that error handling and diagnostics can be handled in a centralized, user-friendly manner?
For example:
A DataHW class handles communication with some data acquisition hardware.
The DataHW class may throw exceptions based on a number of possible errors: intermittent signal, no signal, CRC failure, driver error. Each type of error gets its own exception class.
The DataHW class is called by a number of different pieces of code that do different types of acquisition and analysis.
The proper error handling strategy depends on the type of exception and the operation being attempted. (On intermittent signal, retry X times then tell the user; on a driver error, log an error and restart the driver; etc.) How should this error handling strategy be invoked?
Coding error recovery into each exception class: This would result in exception classes that are rather large and contain high-level UI and system management code. This seems bad.
Providing a separate catch block for each type of exception: Since the DataHW class is called from many different places, each catch block would have to be duplicated at each call site. This seems bad.
Using a single catch block that calls some ExceptionDispatch function with a giant RTTI-based switch statement: RTTI and switch usually indicates a failure to apply OO design, but this seems the least bad alternative.
Avoid duplicating the catch blocks at each call site by catching (...) and calling a shared handler function which rethrows and dispatches:
f()
{
try
{
// something
}
catch (...)
{
handle();
}
}
void handle()
{
try
{
throw;
}
catch (const Foo& e)
{
// handle Foo
}
catch (const Bar& e)
{
// handle Bar
}
// etc
}
An idea I keep running into is that exceptions should be caught by levels which can handle them. For example, a CRC error might be caught by the function that transmits the data, and upon catching this exception, it might try to retransmit, whereas a "no signal" exception might be caught in a higher level and drop or delay the whole operation.
But my guess is that most of these exceptions will be caught around the same function. It is a good idea to catch and handle them seperately (as in soln #2), but you say this causes a lot of duplicate code (leading to soln #3.)
My question is, if there is a lot of code to duplicate, why not make it into a function?
I'm thinking along the lines of...
void SendData(DataHW* data, Destination *dest)
{
try {
data->send(dest);
} catch (CRCError) {
//log error
//retransmit:
data->send(dest);
} catch (UnrecoverableError) {
throw GivingUp;
}
}
I guess it would be like your ExceptionDispatch() function, only instead of switching on the exception type, it would wrap the exception-generating call itself and catch the exceptions.
Of course, this function is overly simplified - you might need a whole wrapper class around DataHW; but my point is, it would be a good idea to have a centralized point around which all DataHW exceptions are handled - if the way different users of the class would handle them are similar.
Perhaps you could write a wrapper class for the DataHW class?
The wrapper would offer the same functionality as the DataHW class, but also contained the needed error handling code. Benefit is that you have the error handling code in a single place (DRY principle), and all errors would be handled uniformly. For example you can translate all low level I/O exceptions to higher level exceptions in the wrapper.
Basically preventing low level exceptions being showed to user.
As Butler Lampson said: All problems in computer science can be solved by another level of indirection
There are three ways i see to solve this.
Writing wrapper functions
Write a wrapper function for each function that can throw exceptions which would handle exceptions. That wrapper is then called by all the callers, instead of the original throwing function.
Using function objects
Another solution is to take a more generic approach and write one function that takes a function object and handles all exceptions. Here is some example:
class DataHW {
public:
template<typename Function>
bool executeAndHandle(Function f) {
for(int tries = 0; ; tries++) {
try {
f(this);
return true;
}
catch(CrcError & e) {
// handle crc error
}
catch(IntermittentSignalError & e) {
// handle intermittent signal
if(tries < 3) {
continue;
} else {
logError("Signal interruption after 3 tries.");
}
}
catch(DriverError & e) {
// restart
}
return false;
}
}
void sendData(char const *data, std::size_t len);
void readData(char *data, std::size_t len);
};
Now if you want to do something, you can just do it:
void doit() {
char buf[] = "hello world";
hw.executeAndHandle(boost::bind(&DataHW::sendData, _1, buf, sizeof buf));
}
Since you provide function objects, you can manage state too. Let's say sendData updates len so that it knows how much bytes were read. Then you can write function objects that read and write and maintain a count for how many characters are read so far.
The downside of this second approach is that you can't access result values of the throwing functions, since they are called from the function object wrappers. There is no easy way to get the result type of a function object binder. One workaround is to write a result function object that is called by executeAndHandle after the execution of the function object succeeded. But if we put too much work into this second approach just to make all the housekeeping work, it's not worth the results anymore.
Combining the two
There is a third option too. We can combine the two solutions (wrapper and function objects).
class DataHW {
public:
template<typename R, typename Function>
R executeAndHandle(Function f) {
for(int tries = 0; ; tries++) {
try {
return f(this);
}
catch(CrcError & e) {
// handle crc error
}
catch(IntermittentSignalError & e) {
// handle intermittent signal
if(tries < 3) {
continue;
} else {
logError("Signal interruption after 3 tries.");
}
}
catch(DriverError & e) {
// restart
}
// return a sensible default. for bool, that's false. for other integer
// types, it's zero.
return R();
}
}
T sendData(char const *data, std::size_t len) {
return executeAndHandle<T>(
boost::bind(&DataHW::doSendData, _1, data, len));
}
// say it returns something for this example
T doSendData(char const *data, std::size_t len);
T doReadData(char *data, std::size_t len);
};
The trick is the return f(); pattern. We can return even when f returns void. This eventually would be my favorite, since it allows both to keep handle code central at one place, but also allows special handling in the wrapper functions. You can decide whether it's better to split this up and make an own class that has that error handler function and the wrappers. Probably that would be a cleaner solution (i think of Separation of Concerns here. One is the basic DataHW functionality and one is the error handling).