From ac2d3624d46b7358dae282ff537d38b2a375aec7 Mon Sep 17 00:00:00 2001 From: Daniel Garcia-Sanchez Date: Wed, 23 Dec 2020 09:58:11 +0100 Subject: [PATCH] Avoid MPI calls in the HDF5 destructors when there is an exception --- source/base/hdf5.cc | 126 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 1 deletion(-) diff --git a/source/base/hdf5.cc b/source/base/hdf5.cc index 2575786a81..9a93bc92b2 100644 --- a/source/base/hdf5.cc +++ b/source/base/hdf5.cc @@ -105,18 +105,80 @@ namespace HDF5 , global_no_collective_cause(H5D_MPIO_SET_INDEPENDENT) { hdf5_reference = std::shared_ptr(new hid_t, [](hid_t *pointer) { +# ifdef DEAL_II_WITH_MPI +# if __cpp_lib_uncaught_exceptions >= 201411 + // std::uncaught_exception() is deprecated in c++17 + if (std::uncaught_exceptions() == 0) +# else + if (std::uncaught_exception() == false) +# endif + { + // Release the HDF5 resource + const herr_t ret = H5Dclose(*pointer); + AssertNothrow(ret >= 0, ExcInternalError()); + (void)ret; + delete pointer; + } + else + { + std::cerr + << "---------------------------------------------------------\n" + << "HDF5 DataSet objects call H5Dclose to end access to the\n" + << "dataset and release resources used by it. This call\n" + << "requires MPI synchronization. Since an exception is\n" + << "currently uncaught, this synchronization will be skipped\n" + << "to avoid a possible deadlock. As a result the HDF5 file\n" + << "might be corrupted.\n" + << "---------------------------------------------------------" + << std::endl; + + MPI_Abort(MPI_COMM_WORLD, 1); + } +# else // Release the HDF5 resource const herr_t ret = H5Dclose(*pointer); AssertNothrow(ret >= 0, ExcInternalError()); (void)ret; delete pointer; +# endif }); - dataspace = std::shared_ptr(new hid_t, [](hid_t *pointer) { + dataspace = std::shared_ptr(new hid_t, [](hid_t *pointer) { +# ifdef DEAL_II_WITH_MPI +# if __cpp_lib_uncaught_exceptions >= 201411 + // std::uncaught_exception() is deprecated in c++17 + if (std::uncaught_exceptions() == 0) +# else + if (std::uncaught_exception() == false) +# endif + { + // Release the HDF5 resource + const herr_t ret = H5Sclose(*pointer); + AssertNothrow(ret >= 0, ExcInternalError()); + (void)ret; + delete pointer; + } + else + { + std::cerr + << "---------------------------------------------------------\n" + << "HDF5 DataSet objects call H5Sclose to end access to the\n" + << "dataspace and release resources used by it. This call\n" + << "requires MPI synchronization. Since an exception is\n" + << "currently uncaught, this synchronization will be skipped\n" + << "to avoid a possible deadlock. As a result the HDF5 file\n" + << "might be corrupted.\n" + << "---------------------------------------------------------" + << std::endl; + + MPI_Abort(MPI_COMM_WORLD, 1); + } +# else // Release the HDF5 resource const herr_t ret = H5Sclose(*pointer); AssertNothrow(ret >= 0, ExcInternalError()); (void)ret; delete pointer; +# endif }); *dataspace = H5Screate_simple(rank, dimensions.data(), nullptr); @@ -279,11 +341,42 @@ namespace HDF5 : HDF5Object(name, mpi) { hdf5_reference = std::shared_ptr(new hid_t, [](hid_t *pointer) { +# ifdef DEAL_II_WITH_MPI +# if __cpp_lib_uncaught_exceptions >= 201411 + // std::uncaught_exception() is deprecated in c++17 + if (std::uncaught_exceptions() == 0) +# else + if (std::uncaught_exception() == false) +# endif + { + // Release the HDF5 resource + const herr_t ret = H5Gclose(*pointer); + AssertNothrow(ret >= 0, ExcInternalError()); + (void)ret; + delete pointer; + } + else + { + std::cerr + << "---------------------------------------------------------\n" + << "HDF5 Group objects call H5Gclose to end access to the\n" + << "group and release resources used by it. This call\n" + << "requires MPI synchronization. Since an exception is\n" + << "currently uncaught, this synchronization will be skipped\n" + << "to avoid a possible deadlock. As a result the HDF5 file\n" + << "might be corrupted.\n" + << "---------------------------------------------------------" + << std::endl; + + MPI_Abort(MPI_COMM_WORLD, 1); + } +# else // Release the HDF5 resource const herr_t ret = H5Gclose(*pointer); AssertNothrow(ret >= 0, ExcInternalError()); (void)ret; delete pointer; +# endif }); switch (mode) { @@ -367,11 +460,42 @@ namespace HDF5 : Group(name, mpi) { hdf5_reference = std::shared_ptr(new hid_t, [](hid_t *pointer) { +# ifdef DEAL_II_WITH_MPI +# if __cpp_lib_uncaught_exceptions >= 201411 + // std::uncaught_exception() is deprecated in c++17 + if (std::uncaught_exceptions() == 0) +# else + if (std::uncaught_exception() == false) +# endif + { + // Release the HDF5 resource + const herr_t err = H5Fclose(*pointer); + AssertNothrow(err >= 0, ExcInternalError()); + (void)err; + delete pointer; + } + else + { + std::cerr + << "---------------------------------------------------------\n" + << "HDF5 File objects call H5Fclose to end access to the\n" + << "file and release resources used by it. This call\n" + << "requires MPI synchronization. Since an exception is\n" + << "currently uncaught, this synchronization will be skipped\n" + << "to avoid a possible deadlock. As a result the HDF5 file\n" + << "might be corrupted.\n" + << "---------------------------------------------------------" + << std::endl; + + MPI_Abort(MPI_COMM_WORLD, 1); + } +# else // Release the HDF5 resource const herr_t err = H5Fclose(*pointer); AssertNothrow(err >= 0, ExcInternalError()); (void)err; delete pointer; +# endif }); hid_t plist; -- 2.39.5