]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Treat the nothrow exception handling special 4862/head
authorDaniel Arndt <daniel.arndt@iwr.uni-heidelberg.de>
Sun, 13 Aug 2017 22:15:48 +0000 (00:15 +0200)
committerDaniel Arndt <daniel.arndt@iwr.uni-heidelberg.de>
Thu, 17 Aug 2017 22:20:01 +0000 (00:20 +0200)
include/deal.II/base/exceptions.h
source/base/exceptions.cc
tests/base/exception_nothrow.cc [new file with mode: 0644]
tests/base/exception_nothrow.debug.output [new file with mode: 0644]
tests/base/reference.debug.output
tests/lac/vector_memory.debug.output

index fb25f459cd80208e5e1d46549ae87da13b77b9fe..d70c4aa50dbd7a75ab695cb3d8a471bbea399bb9 100644 (file)
@@ -234,16 +234,9 @@ namespace deal_II_exceptions
      * 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.
@@ -298,13 +291,29 @@ namespace deal_II_exceptions
           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*/
@@ -355,16 +364,16 @@ 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
 
index 90c8962e8b300fda42677ef97bedc6fe06140fc5..52c23a70c0c108d30ba4cbe0759c8e9c8cd304fc 100644 (file)
@@ -399,68 +399,87 @@ namespace StandardExceptions
 }
 #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;
         }
     }
diff --git a/tests/base/exception_nothrow.cc b/tests/base/exception_nothrow.cc
new file mode 100644 (file)
index 0000000..05f29cf
--- /dev/null
@@ -0,0 +1,26 @@
+// ---------------------------------------------------------------------
+//
+// 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());
+}
diff --git a/tests/base/exception_nothrow.debug.output b/tests/base/exception_nothrow.debug.output
new file mode 100644 (file)
index 0000000..e1b46e4
--- /dev/null
@@ -0,0 +1,12 @@
+
+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)
+--------------------------------------------------------
+
index 26526ec33e182186104974ab101770b488f96eb3..a10c6ffb2804bca0ede52889064d99dd19f695f6 100644 (file)
@@ -11,6 +11,16 @@ DEAL::Construct C
 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
index c3f1dd6d0b5eba7d83f1ab5ff329937f61728ef4..90249144350cebaf16656ba47c4199d79ed92877 100644 (file)
@@ -2,4 +2,24 @@
 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)
+--------------------------------------------------------
+

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.