Catching of sigsegv and sigfpe with structured exceptions on win

This commit is contained in:
tamasmeszaros 2021-06-17 15:04:47 +02:00
parent a5529aff1e
commit 976dd72b8b
8 changed files with 115 additions and 39 deletions

View File

@ -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

View File

@ -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<class Op> 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

View File

@ -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

View File

@ -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)
{

View File

@ -0,0 +1,5 @@
#include "TryCatchSignal.hpp"
#ifdef _MSC_VER
#include "TryCatchSignalSEH.cpp"
#endif

View File

@ -0,0 +1,15 @@
#ifndef TRY_CATCH_SIGNAL_HPP
#define TRY_CATCH_SIGNAL_HPP
#ifdef _MSC_VER
#include "TryCatchSignalSEH.hpp"
#else
template<class TryFn, class CatchFn, int N>
void try_catch_signal(const SignalT (&/*sigs*/)[N], TryFn &&/*fn*/, CatchFn &&/*cfn*/)
{
// TODO
}
#endif
#endif // TRY_CATCH_SIGNAL_HPP

View File

@ -0,0 +1,43 @@
#include "TryCatchSignalSEH.hpp"
#include <windows.h>
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<void()> &&fn,
std::function<void()> &&cfn)
{
__try {
fn();
}
__except(signal_seh_filter(sigcnt, sigs, GetExceptionCode())) {
cfn();
}
}

View File

@ -0,0 +1,27 @@
#ifndef TRY_CATCH_SIGNAL_SEH_HPP
#define TRY_CATCH_SIGNAL_SEH_HPP
#include <functional>
#include <csignal>
namespace Slic3r {
using SignalT = decltype (SIGSEGV);
namespace detail {
void try_catch_signal_seh(int sigcnt, const SignalT *sigs,
std::function<void()> &&fn,
std::function<void()> &&cfn);
}
template<class TryFn, class CatchFn, int N>
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