Fix #144250: Crash when mantaflow solver does not converge and skips cleanup

Mantaflow likes to throw exceptions when things go wrong, which includes a
simple case of the solver not converging sufficiently. This should not be
catastrophic, but cleanup of buffers is omitted when such an exception occurs.
This then leads to yet another failure when the solver is stopped because of
incorrect buffer refcounts. That exception bubbles up through the python layer
and causes errors in the Blender integration wrapper that cause crashes.

Pull Request: https://projects.blender.org/blender/blender/pulls/147527
This commit is contained in:
Lukas Tönne
2025-10-07 15:49:07 +02:00
parent 5df3dd9768
commit 025c401dca
2 changed files with 88 additions and 16 deletions

View File

@@ -0,0 +1,62 @@
diff --git a/extern/mantaflow/preprocessed/plugin/pressure.cpp b/extern/mantaflow/preprocessed/plugin/pressure.cpp
index 593aeb16859..75118a4402a 100644
--- a/extern/mantaflow/preprocessed/plugin/pressure.cpp
+++ b/extern/mantaflow/preprocessed/plugin/pressure.cpp
@@ -1181,7 +1181,27 @@ void solvePressureSystem(Grid<Real> &rhs,
gcg->setMGPreconditioner(GridCgInterface::PC_MGP, pmg);
}
+ auto cleanup = [&](){
+ // Cleanup
+ if (gcg)
+ delete gcg;
+ if (pca0)
+ delete pca0;
+ if (pca1)
+ delete pca1;
+ if (pca2)
+ delete pca2;
+ if (pca3)
+ delete pca3;
+
+ // PcMGDynamic: always delete multigrid solver after use
+ // PcMGStatic: keep multigrid solver for next solve
+ if (pmg && preconditioner == PcMGDynamic)
+ releaseMG(parent);
+ };
+
// CG solve
+ try {
for (int iter = 0; iter < maxIter; iter++) {
if (!gcg->iterate())
iter = maxIter;
@@ -1193,23 +1213,13 @@ void solvePressureSystem(Grid<Real> &rhs,
debMsg("FluidSolver::solvePressure done. Iterations:" << gcg->getIterations()
<< ", residual:" << gcg->getResNorm(),
2);
+ }
+ catch (const Manta::Error &e) {
+ cleanup();
+ throw e;
+ }
- // Cleanup
- if (gcg)
- delete gcg;
- if (pca0)
- delete pca0;
- if (pca1)
- delete pca1;
- if (pca2)
- delete pca2;
- if (pca3)
- delete pca3;
-
- // PcMGDynamic: always delete multigrid solver after use
- // PcMGStatic: keep multigrid solver for next solve
- if (pmg && preconditioner == PcMGDynamic)
- releaseMG(parent);
+ cleanup();
}
static PyObject *_W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{

View File

@@ -1181,19 +1181,7 @@ void solvePressureSystem(Grid<Real> &rhs,
gcg->setMGPreconditioner(GridCgInterface::PC_MGP, pmg); gcg->setMGPreconditioner(GridCgInterface::PC_MGP, pmg);
} }
// CG solve auto cleanup = [&](){
for (int iter = 0; iter < maxIter; iter++) {
if (!gcg->iterate())
iter = maxIter;
if (iter < maxIter)
debMsg("FluidSolver::solvePressure iteration " << iter
<< ", residual: " << gcg->getResNorm(),
9);
}
debMsg("FluidSolver::solvePressure done. Iterations:" << gcg->getIterations()
<< ", residual:" << gcg->getResNorm(),
2);
// Cleanup // Cleanup
if (gcg) if (gcg)
delete gcg; delete gcg;
@@ -1210,6 +1198,28 @@ void solvePressureSystem(Grid<Real> &rhs,
// PcMGStatic: keep multigrid solver for next solve // PcMGStatic: keep multigrid solver for next solve
if (pmg && preconditioner == PcMGDynamic) if (pmg && preconditioner == PcMGDynamic)
releaseMG(parent); releaseMG(parent);
};
// CG solve
try {
for (int iter = 0; iter < maxIter; iter++) {
if (!gcg->iterate())
iter = maxIter;
if (iter < maxIter)
debMsg("FluidSolver::solvePressure iteration " << iter
<< ", residual: " << gcg->getResNorm(),
9);
}
debMsg("FluidSolver::solvePressure done. Iterations:" << gcg->getIterations()
<< ", residual:" << gcg->getResNorm(),
2);
}
catch (const Manta::Error &e) {
cleanup();
throw e;
}
cleanup();
} }
static PyObject *_W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds) static PyObject *_W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{ {