From 976dd72b8b73f66c30889125d8ad213846fad3ac Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 17 Jun 2021 15:04:47 +0200 Subject: [PATCH] Catching of sigsegv and sigfpe with structured exceptions on win --- src/libslic3r/CMakeLists.txt | 3 +- src/libslic3r/MeshBoolean.cpp | 10 +++++- src/libslic3r/MeshBoolean.hpp | 2 ++ src/libslic3r/SLAPrintSteps.cpp | 49 +++++++---------------------- src/libslic3r/TryCatchSignal.cpp | 5 +++ src/libslic3r/TryCatchSignal.hpp | 15 +++++++++ src/libslic3r/TryCatchSignalSEH.cpp | 43 +++++++++++++++++++++++++ src/libslic3r/TryCatchSignalSEH.hpp | 27 ++++++++++++++++ 8 files changed, 115 insertions(+), 39 deletions(-) create mode 100644 src/libslic3r/TryCatchSignal.cpp create mode 100644 src/libslic3r/TryCatchSignal.hpp create mode 100644 src/libslic3r/TryCatchSignalSEH.cpp create mode 100644 src/libslic3r/TryCatchSignalSEH.hpp diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 2b5f3f932..fe09e6557 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -284,7 +284,8 @@ cmake_policy(SET CMP0011 NEW) find_package(CGAL REQUIRED) cmake_policy(POP) -add_library(libslic3r_cgal STATIC MeshBoolean.cpp MeshBoolean.hpp) +add_library(libslic3r_cgal STATIC MeshBoolean.cpp MeshBoolean.hpp TryCatchSignal.hpp + TryCatchSignal.cpp) target_include_directories(libslic3r_cgal PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # Reset compile options of libslic3r_cgal. Despite it being linked privately, CGAL options diff --git a/src/libslic3r/MeshBoolean.cpp b/src/libslic3r/MeshBoolean.cpp index 25ee3e4af..f58ae0bfe 100644 --- a/src/libslic3r/MeshBoolean.cpp +++ b/src/libslic3r/MeshBoolean.cpp @@ -1,6 +1,7 @@ #include "Exception.hpp" #include "MeshBoolean.hpp" #include "libslic3r/TriangleMesh.hpp" +#include "libslic3r/TryCatchSignal.hpp" #undef PI // Include igl first. It defines "L" macro which then clashes with our localization @@ -209,7 +210,9 @@ template void _cgal_do(Op &&op, CGALMesh &A, CGALMesh &B) bool success = false; try { CGALMesh result; - success = op(A, B, result); + try_catch_signal({SIGSEGV, SIGFPE}, [&success, &A, &B, &result, &op] { + success = op(A, B, result); + }, [&] { success = false; }); A = std::move(result); // In-place operation does not work } catch (...) { success = false; @@ -264,6 +267,11 @@ bool does_self_intersect(const TriangleMesh &mesh) void CGALMeshDeleter::operator()(CGALMesh *ptr) { delete ptr; } +bool does_bound_a_volume(const CGALMesh &mesh) +{ + return CGALProc::does_bound_a_volume(mesh.m); +} + } // namespace cgal } // namespace MeshBoolean diff --git a/src/libslic3r/MeshBoolean.hpp b/src/libslic3r/MeshBoolean.hpp index 8e88e2536..4b9686231 100644 --- a/src/libslic3r/MeshBoolean.hpp +++ b/src/libslic3r/MeshBoolean.hpp @@ -54,6 +54,8 @@ void intersect(CGALMesh &A, CGALMesh &B); bool does_self_intersect(const TriangleMesh &mesh); bool does_self_intersect(const CGALMesh &mesh); +bool does_bound_a_volume(const CGALMesh &mesh); + } } // namespace MeshBoolean diff --git a/src/libslic3r/SLAPrintSteps.cpp b/src/libslic3r/SLAPrintSteps.cpp index 5508c9bdc..b267116e9 100644 --- a/src/libslic3r/SLAPrintSteps.cpp +++ b/src/libslic3r/SLAPrintSteps.cpp @@ -428,6 +428,18 @@ void SLAPrint::Steps::drill_holes(SLAPrintObject &po) auto hollowed_mesh_cgal = MeshBoolean::cgal::triangle_mesh_to_cgal(hollowed_mesh); + if (!MeshBoolean::cgal::does_bound_a_volume(*hollowed_mesh_cgal)) { + po.active_step_add_warning(PrintStateBase::WarningLevel::NON_CRITICAL, + L("Mesh to be hollowed is not suitable for hollowing (does not " + "bound a volume).")); + } + + if (!MeshBoolean::cgal::does_bound_a_volume(*holes_mesh_cgal)) { + po.active_step_add_warning(PrintStateBase::WarningLevel::NON_CRITICAL, + L("Unable to drill the current configuration of holes into the " + "model.")); + } + try { MeshBoolean::cgal::minus(*hollowed_mesh_cgal, *holes_mesh_cgal); @@ -749,43 +761,6 @@ void SLAPrint::Steps::slice_supports(SLAPrintObject &po) { report_status(-2, "", SlicingStatus::RELOAD_SLA_PREVIEW); } -//static ClipperPolygons polyunion(const ClipperPolygons &subjects) -//{ -// ClipperLib::Clipper clipper; - -// bool closed = true; - -// for(auto& path : subjects) { -// clipper.AddPath(path.Contour, ClipperLib::ptSubject, closed); -// clipper.AddPaths(path.Holes, ClipperLib::ptSubject, closed); -// } - -// auto mode = ClipperLib::pftPositive; - -// return libnest2d::clipper_execute(clipper, ClipperLib::ctUnion, mode, mode); -//} - -//static ClipperPolygons polydiff(const ClipperPolygons &subjects, const ClipperPolygons& clips) -//{ -// ClipperLib::Clipper clipper; - -// bool closed = true; - -// for(auto& path : subjects) { -// clipper.AddPath(path.Contour, ClipperLib::ptSubject, closed); -// clipper.AddPaths(path.Holes, ClipperLib::ptSubject, closed); -// } - -// for(auto& path : clips) { -// clipper.AddPath(path.Contour, ClipperLib::ptClip, closed); -// clipper.AddPaths(path.Holes, ClipperLib::ptClip, closed); -// } - -// auto mode = ClipperLib::pftPositive; - -// return libnest2d::clipper_execute(clipper, ClipperLib::ctDifference, mode, mode); -//} - // get polygons for all instances in the object static ExPolygons get_all_polygons(const SliceRecord& record, SliceOrigin o) { diff --git a/src/libslic3r/TryCatchSignal.cpp b/src/libslic3r/TryCatchSignal.cpp new file mode 100644 index 000000000..e9dd81a50 --- /dev/null +++ b/src/libslic3r/TryCatchSignal.cpp @@ -0,0 +1,5 @@ +#include "TryCatchSignal.hpp" + +#ifdef _MSC_VER +#include "TryCatchSignalSEH.cpp" +#endif diff --git a/src/libslic3r/TryCatchSignal.hpp b/src/libslic3r/TryCatchSignal.hpp new file mode 100644 index 000000000..5b913aabc --- /dev/null +++ b/src/libslic3r/TryCatchSignal.hpp @@ -0,0 +1,15 @@ +#ifndef TRY_CATCH_SIGNAL_HPP +#define TRY_CATCH_SIGNAL_HPP + +#ifdef _MSC_VER +#include "TryCatchSignalSEH.hpp" +#else +template +void try_catch_signal(const SignalT (&/*sigs*/)[N], TryFn &&/*fn*/, CatchFn &&/*cfn*/) +{ + // TODO +} +#endif + +#endif // TRY_CATCH_SIGNAL_HPP + diff --git a/src/libslic3r/TryCatchSignalSEH.cpp b/src/libslic3r/TryCatchSignalSEH.cpp new file mode 100644 index 000000000..566fe3b4e --- /dev/null +++ b/src/libslic3r/TryCatchSignalSEH.cpp @@ -0,0 +1,43 @@ +#include "TryCatchSignalSEH.hpp" + +#include + +static int signal_seh_filter(int sigcnt, const Slic3r::SignalT *sigs, + unsigned long seh_code) +{ + int ret = EXCEPTION_CONTINUE_SEARCH; + + for (int s = 0; s < sigcnt && ret != EXCEPTION_EXECUTE_HANDLER; ++s) + switch (sigs[s]) { + case SIGSEGV: + if (seh_code == STATUS_ACCESS_VIOLATION) + ret = EXCEPTION_EXECUTE_HANDLER; + break; + case SIGILL: + if (seh_code == STATUS_ILLEGAL_INSTRUCTION) + ret = EXCEPTION_EXECUTE_HANDLER; + break; + case SIGFPE: + if (seh_code == STATUS_FLOAT_DIVIDE_BY_ZERO || + seh_code == STATUS_FLOAT_OVERFLOW || + seh_code == STATUS_FLOAT_UNDERFLOW || + seh_code == STATUS_INTEGER_DIVIDE_BY_ZERO) + ret = EXCEPTION_EXECUTE_HANDLER; + break; + default: ret = EXCEPTION_CONTINUE_SEARCH; + } + + return ret; +} + +void Slic3r::detail::try_catch_signal_seh(int sigcnt, const SignalT *sigs, + std::function &&fn, + std::function &&cfn) +{ + __try { + fn(); + } + __except(signal_seh_filter(sigcnt, sigs, GetExceptionCode())) { + cfn(); + } +} diff --git a/src/libslic3r/TryCatchSignalSEH.hpp b/src/libslic3r/TryCatchSignalSEH.hpp new file mode 100644 index 000000000..72f45d4ff --- /dev/null +++ b/src/libslic3r/TryCatchSignalSEH.hpp @@ -0,0 +1,27 @@ +#ifndef TRY_CATCH_SIGNAL_SEH_HPP +#define TRY_CATCH_SIGNAL_SEH_HPP + +#include +#include + +namespace Slic3r { + +using SignalT = decltype (SIGSEGV); + +namespace detail { + +void try_catch_signal_seh(int sigcnt, const SignalT *sigs, + std::function &&fn, + std::function &&cfn); + +} + +template +void try_catch_signal(const SignalT (&sigs)[N], TryFn &&fn, CatchFn &&cfn) +{ + detail::try_catch_signal_seh(N, sigs, fn, cfn); +} + +} // Slic3r + +#endif // TRY_CATCH_SIGNAL_SEH_HPP