Skip to content

Commit 2c117a5

Browse files
authored
Fix crashes due to uncaught exceptions in ~FinalStateStorer (AMICI-dev#2647)
Due to LLNL/sundials#82, we can get exceptions from `CVodeSolver::getSens`, escaping `FinalStateStorer::~FinalStateStorer`, that will result in crashes. This is fixed here. The issue is semi-producible with [Boehm_JProteomeRes2014](https://github.com/Benchmarking-Initiative/Benchmark-Models-PEtab/tree/15b4f78aff1121870537ad3e1a6b902cb8f73930/Benchmark-Models/Boehm_JProteomeRes2014) with forward sensitivities: Program output: ``` 2025-02-17 14:44:33.988 - amici.swig_wrappers - DEBUG - [model1_data1][cvodes:CVode:WARNING] python/sdist/amici/ThirdParty/sundials/src/cvodes/cvodes.c:3482: Internal t = 0 and h = 0 are such that t + h = t on the next step. The solver will continue anyway. (99) 2025-02-17 14:44:33.988 - amici.swig_wrappers - DEBUG - [model1_data1][cvodes:CVodeGetDky:BAD_T] python/sdist/amici/ThirdParty/sundials/src/cvodes/cvodes.c:3783: Illegal value for t.t = 2.5 is not between tcur - hu = 0 and tcur = 0. (-25) 2025-02-17 14:44:33.988 - amici.swig_wrappers - DEBUG - [model1_data1][cvodes:CVodeGetDky:BAD_T] python/sdist/amici/ThirdParty/sundials/src/cvodes/cvodes.c:3783: Illegal value for t.t = 5 is not between tcur - hu = 0 and tcur = 0. (-25) 2025-02-17 14:44:33.988 - amici.swig_wrappers - DEBUG - [model1_data1][cvodes:CVode:ILL_INPUT] python/sdist/amici/ThirdParty/sundials/src/cvodes/cvodes.c:3328: Trouble interpolating at tout = 5. tout too far back in direction of integration (-22) 2025-02-17 14:44:33.988 - amici.swig_wrappers - ERROR - [model1_data1][FORWARD_FAILURE] AMICI forward simulation failed at t = 5: AMICI failed to integrate the forward problem terminate called after throwing an instance of 'amici::CvodeException' what(): CVODE routine CVodeGetSens failed with error code -25. Thread 1 "python" received signal SIGABRT, Aborted. ``` Stack trace: ``` AMICI-dev#10 0x00007ffff70811f1 in _Unwind_RaiseException (exc=0x6d5ff10) at ../../../src/libgcc/unwind.inc:136 AMICI-dev#11 0x00007ffff48bb384 in __cxxabiv1::__cxa_throw (obj=<optimized out>, tinfo=0x7fff5c6d6aa8 <typeinfo for amici::CvodeException>, dest=0x7fff5c5476c4 <amici::CvodeException::~CvodeException()>) at ../../../../src/libstdc++-v3/libsupc++/eh_throw.cc:93 AMICI-dev#12 0x00007fff5c5bdb64 in amici::CVodeSolver::getSens (this=0x6d130d0) at python/sdist/amici/src/solver_cvodes.cpp:663 AMICI-dev#13 0x00007fffbc5709e8 in amici::Solver::getStateSensitivity (this=0x6d130d0, t=2.5) at python/sdist/amici/src/solver.cpp:1340 AMICI-dev#14 0x00007fffbc570750 in amici::Solver::writeSolution (this=0x6d130d0, t=0x6d26db0, x=..., dx=..., sx=..., xQ=...) at python/sdist/amici/src/solver.cpp:1303 AMICI-dev#15 0x00007fffbc5d376d in amici::ForwardProblem::getSimulationState (this=0x6d26c90) at python/sdist/amici/src/forwardproblem.cpp:421 AMICI-dev#16 0x00007fffbc5d45df in amici::FinalStateStorer::~FinalStateStorer (this=0x7fffffffb308, __in_chrg=<optimized out>) at include/amici/forwardproblem.h:450 AMICI-dev#17 0x00007fffbc5d2285 in amici::ForwardProblem::workForwardProblem (this=0x6d26c90) at python/sdist/amici/src/forwardproblem.cpp:203 AMICI-dev#18 0x00007fffbc54fbf9 in amici::runAmiciSimulation (solver=..., edata=0x5078010, model=..., rethrow=false) at python/sdist/amici/src/amici.cpp:108 ```
1 parent 8366b87 commit 2c117a5

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

include/amici/forwardproblem.h

+30-12
Original file line numberDiff line numberDiff line change
@@ -441,19 +441,37 @@ class FinalStateStorer : public ContextManager {
441441
/**
442442
* @brief destructor, stores simulation state
443443
*/
444-
~FinalStateStorer() {
444+
~FinalStateStorer() noexcept(false) {
445445
if (fwd_) {
446-
fwd_->final_state_ = fwd_->getSimulationState();
447-
// if there is an associated output timepoint, also store it in
448-
// timepoint_states if it's not present there.
449-
// this may happen if there is an error just at
450-
// (or indistinguishably before) an output timepoint
451-
auto final_time = fwd_->getFinalTime();
452-
auto const timepoints = fwd_->model->getTimepoints();
453-
if (!fwd_->timepoint_states_.count(final_time)
454-
&& std::find(timepoints.cbegin(), timepoints.cend(), final_time)
455-
!= timepoints.cend()) {
456-
fwd_->timepoint_states_[final_time] = fwd_->final_state_;
446+
try {
447+
// This may throw in `CVodeSolver::getSens`
448+
// due to https://github.com/LLNL/sundials/issues/82.
449+
// Therefore, this dtor must be `noexcept(false)` to avoid
450+
// programm termination.
451+
fwd_->final_state_ = fwd_->getSimulationState();
452+
// if there is an associated output timepoint, also store it in
453+
// timepoint_states if it's not present there.
454+
// this may happen if there is an error just at
455+
// (or indistinguishably before) an output timepoint
456+
auto final_time = fwd_->getFinalTime();
457+
auto const timepoints = fwd_->model->getTimepoints();
458+
if (!fwd_->timepoint_states_.count(final_time)
459+
&& std::find(timepoints.cbegin(), timepoints.cend(), final_time)
460+
!= timepoints.cend()) {
461+
fwd_->timepoint_states_[final_time] = fwd_->final_state_;
462+
}
463+
} catch (std::exception const&) {
464+
// We must not throw in case we are already in the stack
465+
// unwinding phase due to some other active exception, otherwise
466+
// this will also lead to termination.
467+
//
468+
// In case there is another active exception,
469+
// `fwd_->{final_state_,timepoint_states_}` won't be set,
470+
// and we assume that they are either not accessed anymore, or
471+
// that there is appropriate error handling in place.
472+
if(!std::uncaught_exceptions()) {
473+
throw;
474+
}
457475
}
458476
}
459477
}

0 commit comments

Comments
 (0)