From 025c401dca087ed9c657358124be2a817dcc4cf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Tue, 7 Oct 2025 15:49:07 +0200 Subject: [PATCH] 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 --- .../patches/fix-solver-error-cleanup.patch | 62 +++++++++++++++++++ .../preprocessed/plugin/pressure.cpp | 42 ++++++++----- 2 files changed, 88 insertions(+), 16 deletions(-) create mode 100644 extern/mantaflow/patches/fix-solver-error-cleanup.patch diff --git a/extern/mantaflow/patches/fix-solver-error-cleanup.patch b/extern/mantaflow/patches/fix-solver-error-cleanup.patch new file mode 100644 index 00000000000..acb205b2872 --- /dev/null +++ b/extern/mantaflow/patches/fix-solver-error-cleanup.patch @@ -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 &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 &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) + { 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 &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 &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) {