2

I have a exception safety issue on InitOnceExecuteOnce WinAPI function. Whenever exception is thrown from callback function deadlock is occurred. Callback returns boolean flag telling the caller whether the data is successfully initialized, but if I return false I will not be able to rethrow exception, that's not good. I tried solved the problem this way.

try
{
    InitOnceExecuteOnce(&flag, init_once_handler, &arguments, 0);
} catch (...)
{
    InitOnceInitialize(&flag);
    throw;
}

Whenever I catch an exception from function I init the structure once again and rethrow the exception, so other threads will find the data not initialized, as the flag is in initial state. However, it sometimes deadlocks too, possibly because other thread started waiting on the synchronization object before the first one caught the exception and initialized flag once again. Is there any solution to that problem?

Thanks in advance.

axe
  • 217
  • 3
  • 9

1 Answers1

6

You should not throw C++ exceptions through code that does not expect it, (eg. C code, or in your case, the Windows API). instead, have your callback return false on error, which will be reflected in the return from InitOnceExecuteOnce

Hasturkun
  • 35,395
  • 6
  • 71
  • 104
  • That's a user-defined function, I can't give that guarantee. That's a C++ code which uses containers, algorithms and there might be exceptions on every step, what I should do is avoid problems in result of this function execution and also I would like to propagate the exception to the caller, but this causes deadlock. Maybe there is another mechanism which allows that? – axe Jan 27 '11 at 18:59
  • 1
    @axe: If so, wrap that callback with your own, your callback catches the exception and returns false. you may optionally wrap the function's argument in a struct, allowing you to return information about the exception from the callback. – Hasturkun Jan 27 '11 at 19:01
  • I've already done this, I also wrapped the exception object with polymorph class which rethrows exception (something like boost::current_exception), however that allows me to rethrow only predefined set of exceptions, if user throw some user-defined class object he will catch std::runtime_error("unknown exception"). Good enough, but could be better. – axe Jan 27 '11 at 19:04
  • 2
    @axe: If you can't make that guarantee, then enjoy your deadlock. If you want to avoid deadlock, catch your exceptions inside your callback function, save the exception somewhere (e.g. use the context parameter), and return an error code. If `InitOnceExecuteOnce` returns that error code, grab the saved copy of the exception and rethrow it. – Adam Rosenfield Jan 27 '11 at 19:05
  • Done with exception wrappers. Thanks to everybody. – axe Jan 28 '11 at 17:19