bin: handle any exception before returning from parse_opt()

On some architectures (e.g., ARM, or even some -flto setups on Intel)
C++ exceptions to not traverse the C functions.  So even if the C++
main() has a try/catch, it will not catch the exception thrown by C++
code called from the argp module (which is compiled in C).

* bin/common_setup.cc, bin/common_setup.hh: Define some macros
and function to factorize exception handling.
* bin/autcross.cc, bin/autfilt.cc, bin/common_aoutput.cc,
bin/common_color.cc, bin/common_finput.cc, bin/common_hoaread.cc,
bin/common_output.cc, bin/common_post.cc, bin/common_trans.cc,
bin/dstar2tgba.cc, bin/genaut.cc, bin/genltl.cc, bin/ltl2tgba.cc,
bin/ltl2tgta.cc, bin/ltlcross.cc, bin/ltldo.cc, bin/ltlfilt.cc,
bin/ltlgrind.cc, bin/ltlsynt.cc, bin/randaut.cc, bin/randltl.cc:
Protect all parse_opt() functions, even those where there is currently
no exception risk.
This commit is contained in:
Alexandre Duret-Lutz 2019-09-25 21:57:25 +02:00
parent 74ceea89ee
commit d523ce8ba4
23 changed files with 104 additions and 19 deletions

View file

@ -150,6 +150,8 @@ static const argp_option options_hidden[] =
static int
parse_opt_misc(int key, char*, struct argp_state* state)
{
// Called from C code, so should not raise any exception.
BEGIN_EXCEPTION_PROTECT;
// This switch is alphabetically-ordered.
switch (key)
{
@ -170,6 +172,7 @@ parse_opt_misc(int key, char*, struct argp_state* state)
default:
return ARGP_ERR_UNKNOWN;
}
END_EXCEPTION_PROTECT;
return 0;
}
@ -181,6 +184,18 @@ const struct argp misc_argp_hidden = { options_hidden, parse_opt_misc,
nullptr, nullptr, nullptr,
nullptr, nullptr };
[[noreturn]] void handle_any_exception()
{
try
{
throw;
}
catch (const std::exception& e)
{
error(2, 0, "%s", e.what());
}
SPOT_UNREACHABLE();
}
int protected_main(char** progname, std::function<int()> mainfun)
{
@ -189,13 +204,9 @@ int protected_main(char** progname, std::function<int()> mainfun)
setup(progname);
return mainfun();
}
catch (const std::runtime_error& e)
catch (...)
{
error(2, 0, "%s", e.what());
}
catch (const std::invalid_argument& e)
{
error(2, 0, "%s", e.what());
handle_any_exception();
}
SPOT_UNREACHABLE();
return 2;