* Depending on whether deal_II_exceptions::disable_abort_on_exception was
* called, this function either aborts the program flow by printing the
* error message provided by @p exc and calling <tt>std::abort()</tt>, or
- * throws @p exc instead (if @p nothrow is set to <tt>false</tt>).
- *
- * If the boolean @p nothrow is set to true and
- * deal_II_exceptions::disable_abort_on_exception was called, the
- * exception type is just printed to deallog and program flow
- * continues. This is useful if throwing an exception is prohibited
- * (e.g. in a destructor with <tt>noexcept(true)</tt> or
- * <tt>throw()</tt>).
+ * throws @p exc instead.
*/
- void abort (const ExceptionBase &exc, bool nothrow = false);
+ void abort (const ExceptionBase &exc);
/**
* An enum describing how to treat an exception in issue_error.
dealii::deal_II_exceptions::internals::abort(e);
break;
case abort_nothrow_on_exception:
- dealii::deal_II_exceptions::internals::abort(e, /*nothrow =*/ true);
+ // The proper way is to call the function below directly
+ // to preserve the noexcept specifier.
+ // For reasons of backward compatibility
+ // we treat this case here as well.
+ issue_error_nothrow(handling, file, line, function, cond, exc_name, e);
break;
case throw_on_exception:
throw e;
}
}
+ /**
+ * Exception generation mechanism in case we must not throw.
+ *
+ * @ref ExceptionBase
+ */
+ void issue_error_nothrow (ExceptionHandling,
+ const char *file,
+ int line,
+ const char *function,
+ const char *cond,
+ const char *exc_name,
+ ExceptionBase e) noexcept;
} /*namespace internals*/
} /*namespace deal_II_exceptions*/
* @author Wolfgang Bangerth, 1997, 1998, Matthias Maier, 2013
*/
#ifdef DEBUG
-#define AssertNothrow(cond, exc) \
- { \
- if (!(cond)) \
- ::dealii::deal_II_exceptions::internals:: \
- issue_error( \
+#define AssertNothrow(cond, exc) \
+ { \
+ if (!(cond)) \
+ ::dealii::deal_II_exceptions::internals:: \
+ issue_error_nothrow( \
::dealii::deal_II_exceptions::internals::abort_nothrow_on_exception, \
__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #exc, exc); \
}
#else
-#define AssertNothrow(cond, exc) \
+#define AssertNothrow(cond, exc) \
{}
#endif
}
#endif // DEAL_II_WITH_MPI
-
+namespace
+{
+ void internal_abort (const ExceptionBase &exc) noexcept
+ {
+ // first print the error
+ std::cerr << exc.what() << std::endl;
+
+ // then bail out. if in MPI mode, bring down the entire
+ // house by asking the MPI system to do a best-effort
+ // operation at also terminating all of the other MPI
+ // processes. this is useful because if only one process
+ // runs into an assertion, then that may lead to deadlocks
+ // if the others don't recognize this, or at the very least
+ // delay their termination until they realize that their
+ // communication with the job that died times out.
+ //
+ // Unlike std::abort(), MPI_Abort() unfortunately doesn't break when
+ // running inside a debugger like GDB, so only use this strategy if
+ // absolutely necessary and inform the user how to use a debugger.
+#ifdef DEAL_II_WITH_MPI
+ int is_initialized;
+ MPI_Initialized(&is_initialized);
+ if (is_initialized)
+ {
+ // do the same as in Utilities::MPI::n_mpi_processes() here,
+ // but without error checking to not throw again.
+ int n_proc=1;
+ MPI_Comm_size (MPI_COMM_WORLD, &n_proc);
+ if (n_proc>1)
+ {
+ std::cerr << "Calling MPI_Abort now.\n"
+ << "To break execution in a GDB session, execute 'break MPI_Abort' before "
+ << "running. You can also put the following into your ~/.gdbinit:\n"
+ << " set breakpoint pending on\n"
+ << " break MPI_Abort\n"
+ << " set breakpoint pending auto" << std::endl;
+
+ MPI_Abort (MPI_COMM_WORLD,
+ /* return code = */ 255);
+ }
+ }
+#endif
+ std::abort();
+ }
+}
namespace deal_II_exceptions
{
namespace internals
{
- void abort (const ExceptionBase &exc, bool nothrow /*= false*/)
+ void issue_error_nothrow (ExceptionHandling,
+ const char *file,
+ int line,
+ const char *function,
+ const char *cond,
+ const char *exc_name,
+ ExceptionBase e) noexcept
{
+ // Fill the fields of the exception object
+ e.set_fields (file, line, function, cond, exc_name);
if (dealii::deal_II_exceptions::abort_on_exception)
- {
- // first print the error
- std::cerr << exc.what() << std::endl;
-
- // then bail out. if in MPI mode, bring down the entire
- // house by asking the MPI system to do a best-effort
- // operation at also terminating all of the other MPI
- // processes. this is useful because if only one process
- // runs into an assertion, then that may lead to deadlocks
- // if the others don't recognize this, or at the very least
- // delay their termination until they realize that their
- // communication with the job that died times out.
- //
- // Unlike std::abort(), MPI_Abort() unfortunately doesn't break when
- // running inside a debugger like GDB, so only use this strategy if
- // absolutely necessary and inform the user how to use a debugger.
-#ifdef DEAL_II_WITH_MPI
- int is_initialized;
- MPI_Initialized(&is_initialized);
- if (is_initialized)
- {
- const unsigned int n_proc = Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD);
- if (n_proc>1)
- {
- std::cerr << "Calling MPI_Abort now.\n"
- << "To break execution in a GDB session, execute 'break MPI_Abort' before "
- << "running. You can also put the following into your ~/.gdbinit:\n"
- << " set breakpoint pending on\n"
- << " break MPI_Abort\n"
- << " set breakpoint pending auto" << std::endl;
-
- MPI_Abort (MPI_COMM_WORLD,
- /* return code = */ 255);
- }
- }
- std::abort ();
-#else
- std::abort();
-#endif
- }
- else if (nothrow)
+ internal_abort(e);
+ else
{
// We are not allowed to throw, and not allowed to abort.
- // Just print the exception name to deallog and continue
- // normally:
- deallog << "Exception: " << exc.get_exc_name() << std::endl;
+ // Just print the exception name to deallog and continue normally:
+ deallog << "Exception: " << e.get_exc_name() << std::endl;
+ deallog << e.what() << std::endl;
}
+ }
+
+
+
+ void abort (const ExceptionBase &exc)
+ {
+ if (dealii::deal_II_exceptions::abort_on_exception)
+ internal_abort(exc);
else
{
- // We are not allowed to abort, so just throw the error so just
- // throw the error so just throw the error so just throw the
- // error:
+ // We are not allowed to abort, so just throw the error:
throw exc;
}
}
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2017 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+// test that AssertNothrow is printing what we expect.
+
+#include "../tests.h"
+
+int main ()
+{
+ initlog();
+ deal_II_exceptions::disable_abort_on_exception();
+ AssertNothrow(1==2, ExcInternalError());
+}
--- /dev/null
+
+DEAL::Exception: ExcInternalError()
+DEAL::
+--------------------------------------------------------
+An error occurred in file <exception_nothrow.cc> in function
+ int main()
+The violated condition was:
+ 1==2
+Additional information:
+ (none)
+--------------------------------------------------------
+
DEAL::Construct D
DEAL::Destruct D
DEAL::Exception: ExcInUse (counter, object_info->name(), infostring)
+DEAL::
+--------------------------------------------------------
+An error occurred in file <subscriptor.cc> in function
+ void dealii::Subscriptor::check_no_subscribers() const
+The violated condition was:
+ counter == 0
+Additional information:
+ (none)
+--------------------------------------------------------
+
DEAL::Destruct C
DEAL::Destruct B
DEAL::Destruct A
DEAL::GrowingVectorMemory:Overall allocated vectors: 10
DEAL::GrowingVectorMemory:Maximum allocated vectors: 6
DEAL::Exception: StandardExceptions::ExcMemoryLeak(current_alloc)
+DEAL::
+--------------------------------------------------------
+An error occurred in file <vector_memory.templates.h> in function
+ dealii::GrowingVectorMemory<VectorType>::~GrowingVectorMemory() [with VectorType = dealii::Vector<double>]
+The violated condition was:
+ current_alloc == 0
+Additional information:
+ (none)
+--------------------------------------------------------
+
DEAL::Exception: StandardExceptions::ExcMemoryLeak(current_alloc)
+DEAL::
+--------------------------------------------------------
+An error occurred in file <vector_memory.templates.h> in function
+ dealii::GrowingVectorMemory<VectorType>::~GrowingVectorMemory() [with VectorType = dealii::Vector<float>]
+The violated condition was:
+ current_alloc == 0
+Additional information:
+ (none)
+--------------------------------------------------------
+