Uncertain_conversion_exception when using Emscripten to compile CGAL to Wasm
Closed this issue · 5 comments
Issue Details
I'm compiling CGAL to WebAssembly using Emscripten. Quite some things seem to work; however, sometimes I get the Uncertain_conversion_exception at runtime causing the JavaScript/Wasm program to crash, while the local C++ version runs fine.
Source Code
Here is a minimal program that crashes.
#include <CGAL/approximated_offset_2.h>
#include <CGAL/Gps_circle_segment_traits_2.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
using Exact = CGAL::Exact_predicates_exact_constructions_kernel;
template <class K> using Point = CGAL::Point_2<K>;
template <class K> using Polygon = CGAL::Polygon_2<K>;
int main(int argc, char* argv[]) {
std::vector<Point<Exact>> points({{200, -400}, {300, -500}});
Polygon<Exact> polygon(points.begin(), points.end());
auto dilation = CGAL::approximated_offset_2(polygon, 50.0, 0.0000001);
return 0;
}I compile it using CMake / Emscripten using the following CMake file (note the compile flags).
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(wasm-test
LANGUAGES CXX)
if(EMSCRIPTEN)
add_compile_definitions(
USE_BOOST_HEADERS=1
CGAL_ALWAYS_ROUND_TO_NEAREST
CGAL_DISABLE_GMP=ON
NO_DISABLE_EXCEPTION_CATCHING
)
include_directories(${CMAKE_SOURCE_DIR}/lib)
else()
find_package(CGAL REQUIRED)
include_directories(${CGAL_INCLUDE_DIR})
link_libraries(${CGAL_LIBRARIES})
find_package(GMP REQUIRED)
endif()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(wasm-test
src/test.cpp
)
if(EMSCRIPTEN)
set_target_properties(wasm-test PROPERTIES
LINK_FLAGS "-sNO_DISABLE_EXCEPTION_CATCHING -g"
)
endif()
target_link_libraries(wasm-test)- lib
- CGAL (this is a symlink to /usr/include/CGAL where my CGAL headers are installed)
- src
- test.cpp
- CMakeLists.txt
Steps to reproduce
- Install dependencies and set up directory structure above, move to root.
mkdir wasm && cd wasmemcmake cmake ..emmake makenode wasm-test.js- Get the stack trace listed below
Stack trace
/home/steven/Documents/wasm-test/wasm/wasm-test.js:1128
exceptionLast = new CppException(ptr);
^
CGAL::Uncertain_conversion_exception: Undecidable conversion of CGAL::Uncertain<T>
at ___cxa_throw (/home/steven/Documents/wasm-test/wasm/wasm-test.js:1128:23)
at wasm-test.wasm.CGAL::Uncertain<bool>::make_certain() const (wasm://wasm/wasm-test.wasm-0714c812:wasm-function[1206]:0x2bc29)
at wasm-test.wasm.CGAL::Uncertain<bool>::operator bool() const (wasm://wasm/wasm-test.wasm-0714c812:wasm-function[1202]:0x2badd)
at wasm-test.wasm.void CGAL::line_from_pointsC2<CGAL::Interval_nt<false>>(CGAL::Interval_nt<false> const&, CGAL::Interval_nt<false> const&, CGAL::Interval_nt<false> const&, CGAL::Interval_nt<false> const&, CGAL::Interval_nt<false>&, CGAL::Interval_nt<false>&, CGAL::Interval_nt<false>&) (wasm://wasm/wasm-test.wasm-0714c812:wasm-function[2409]:0x4d93d)
at wasm-test.wasm.CGAL::CartesianKernelFunctors::Construct_line_2<CGAL::Simple_cartesian<CGAL::Interval_nt<false>>>::operator()(CGAL::Return_base_tag, CGAL::Point_2<CGAL::Simple_cartesian<CGAL::Interval_nt<false>>> const&, CGAL::Point_2<CGAL::Simple_cartesian<CGAL::Interval_nt<false>>> const&) const (wasm://wasm/wasm-test.wasm-0714c812:wasm-function[2406]:0x4d7c5)
at wasm-test.wasm.CGAL::Lazy_rep_n<CGAL::Line_2<CGAL::Simple_cartesian<CGAL::Interval_nt<false>>>, CGAL::Line_2<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::rational_adaptor<boost::multiprecision::backends::cpp_int_backend<0ul, 0ul, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__2::allocator<unsigned long long>>>, (boost::multiprecision::expression_template_option)1>>>, CGAL::CartesianKernelFunctors::Construct_line_2<CGAL::Simple_cartesian<CGAL::Interval_nt<false>>>, CGAL::CartesianKernelFunctors::Construct_line_2<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::rational_adaptor<boost::multiprecision::backends::cpp_int_backend<0ul, 0ul, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__2::allocator<unsigned long long>>>, (boost::multiprecision::expression_template_option)1>>>, CGAL::Cartesian_converter<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::rational_adaptor<boost::multiprecision::backends::cpp_int_backend<0ul, 0ul, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__2::allocator<unsigned long long>>>, (boost::multiprecision::expression_template_option)1>>, CGAL::Simple_cartesian<CGAL::Interval_nt<false>>, CGAL::NT_converter<boost::multiprecision::number<boost::multiprecision::backends::rational_adaptor<boost::multiprecision::backends::cpp_int_backend<0ul, 0ul, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__2::allocator<unsigned long long>>>, (boost::multiprecision::expression_template_option)1>, CGAL::Interval_nt<false>>>, false, CGAL::Return_base_tag, CGAL::Point_2<CGAL::Epeck>, CGAL::Point_2<CGAL::Epeck>>::Lazy_rep_n<CGAL::Return_base_tag const&, CGAL::Point_2<CGAL::Epeck> const&, CGAL::Point_2<CGAL::Epeck> const&>(CGAL::CartesianKernelFunctors::Construct_line_2<CGAL::Simple_cartesian<CGAL::Interval_nt<false>>> const&, CGAL::CartesianKernelFunctors::Construct_line_2<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::rational_adaptor<boost::multiprecision::backends::cpp_int_backend<0ul, 0ul, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__2::allocator<unsigned long long>>>, (boost::multiprecision::expression_template_option)1>>> const&, CGAL::Return_base_tag const&, CGAL::Point_2<CGAL::Epeck> const&, CGAL::Point_2<CGAL::Epeck> const&) (wasm://wasm/wasm-test.wasm-0714c812:wasm-function[2405]:0x4d680)
at wasm-test.wasm.decltype(auto) CGAL::Lazy_construction<CGAL::Epeck, CGAL::CartesianKernelFunctors::Construct_line_2<CGAL::Simple_cartesian<CGAL::Interval_nt<false>>>, CGAL::CartesianKernelFunctors::Construct_line_2<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::rational_adaptor<boost::multiprecision::backends::cpp_int_backend<0ul, 0ul, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__2::allocator<unsigned long long>>>, (boost::multiprecision::expression_template_option)1>>>, CGAL::Default, true>::operator()<CGAL::Return_base_tag, CGAL::Point_2<CGAL::Epeck>, CGAL::Point_2<CGAL::Epeck>>(CGAL::Return_base_tag const&, CGAL::Point_2<CGAL::Epeck> const&, CGAL::Point_2<CGAL::Epeck> const&) const (wasm://wasm/wasm-test.wasm-0714c812:wasm-function[2397]:0x4d348)
at wasm-test.wasm.CGAL::Line_2<CGAL::Epeck>::Line_2(CGAL::Point_2<CGAL::Epeck> const&, CGAL::Point_2<CGAL::Epeck> const&) (wasm://wasm/wasm-test.wasm-0714c812:wasm-function[2014]:0x44491)
at wasm-test.wasm.CGAL::_X_monotone_circle_segment_2<CGAL::Epeck, true>::_X_monotone_circle_segment_2(CGAL::Point_2<CGAL::Epeck> const&, CGAL::Point_2<CGAL::Epeck> const&) (wasm://wasm/wasm-test.wasm-0714c812:wasm-function[951]:0x21b31)
at wasm-test.wasm.std::__2::back_insert_iterator<std::__2::list<CGAL::Arr_labeled_traits_2<CGAL::Gps_circle_segment_traits_2<CGAL::Epeck, true>>::X_monotone_curve_2, std::__2::allocator<CGAL::Arr_labeled_traits_2<CGAL::Gps_circle_segment_traits_2<CGAL::Epeck, true>>::X_monotone_curve_2>>> CGAL::Approx_offset_base_2<CGAL::Epeck, std::__2::vector<CGAL::Point_2<CGAL::Epeck>, std::__2::allocator<CGAL::Point_2<CGAL::Epeck>>>>::_offset_polygon<std::__2::back_insert_iterator<std::__2::list<CGAL::Arr_labeled_traits_2<CGAL::Gps_circle_segment_traits_2<CGAL::Epeck, true>>::X_monotone_curve_2, std::__2::allocator<CGAL::Arr_labeled_traits_2<CGAL::Gps_circle_segment_traits_2<CGAL::Epeck, true>>::X_monotone_curve_2>>>>(CGAL::Polygon_2<CGAL::Epeck, std::__2::vector<CGAL::Point_2<CGAL::Epeck>, std::__2::allocator<CGAL::Point_2<CGAL::Epeck>>>> const&, CGAL::Sign, CGAL::Lazy_exact_nt<boost::multiprecision::number<boost::multiprecision::backends::rational_adaptor<boost::multiprecision::backends::cpp_int_backend<0ul, 0ul, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__2::allocator<unsigned long long>>>, (boost::multiprecision::expression_template_option)1>> const&, unsigned int, std::__2::back_insert_iterator<std::__2::list<CGAL::Arr_labeled_traits_2<CGAL::Gps_circle_segment_traits_2<CGAL::Epeck, true>>::X_monotone_curve_2, std::__2::allocator<CGAL::Arr_labeled_traits_2<CGAL::Gps_circle_segment_traits_2<CGAL::Epeck, true>>::X_monotone_curve_2>>>) const (wasm://wasm/wasm-test.wasm-0714c812:wasm-function[895]:0x1f3fc) {
excPtr: 168536
}
Environment
- Operating system (Windows/Mac/Linux, 32/64 bits): JS/Wasm on WSL2 Ubuntu 25.04 on Windows 11
- Compiler: Emscripten
- CGAL version: 6.0.1-1
- Boost version: 1.83.0.2
Try defining CGAL_ALWAYS_ROUND_TO_NEAREST before including any CGAL header.
As you can see in the CMakeLists.txt I included, I define it there using add_compile_definitions. Defining it in the cpp file using #define CGAL_ALWAYS_ROUND_TO_NEAREST makes no difference and gives a warning that it is already defined.
I missed that there were some collapsed parts...
I can't really reproduce as it requires a 32 bits env (at least when using your cmake script). I'd need to run it in a docker but I don't have time right now.
I figured out the problem. The issue turned out to be not correctly passing the flags to turn off the default disabling of exception catching by Emscripten. My current CMakeLists.txt file with which compilation succeeds is given below.
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(wasm-test
LANGUAGES CXX)
if(EMSCRIPTEN)
add_compile_definitions(
USE_BOOST_HEADERS=1
CGAL_ALWAYS_ROUND_TO_NEAREST
CGAL_DISABLE_GMP=ON
)
include_directories(${CMAKE_SOURCE_DIR}/lib)
else()
find_package(CGAL REQUIRED)
include_directories(${CGAL_INCLUDE_DIR})
link_libraries(${CGAL_LIBRARIES})
find_package(GMP REQUIRED)
endif()
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(wasm-test
src/test.cpp
)
if(EMSCRIPTEN)
set_target_properties(wasm-test PROPERTIES
LINK_FLAGS "-g -fwasm-exceptions"
)
target_compile_options(wasm-test PRIVATE -fwasm-exceptions)
endif()
target_link_libraries(wasm-test)