dune-alugrid  2.6-git
duneassert.hh
Go to the documentation of this file.
1 #ifndef DUNE_ASSERT_HH
2 #define DUNE_ASSERT_HH
3 
4 #include <cstdlib>
5 #include <unistd.h>
6 #include <iostream>
7 #if HAVE_MPI
8 #include <mpi.h>
9 #endif
10 
11 // combination of suggestions made in
12 // http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
13 // and
14 // http://www.open-mpi.de/faq/?category=debugging
15 
16 namespace
17 {
18  // Call to stop a program so that it is possible to attach a debugger.
19  // The process id (PID) and calling host are printed to the error stream
20  // If the parameter p is added in a parallel code only the process with
21  // that rank will wait to allow a debugger to attach.
22  //
23  // To attach for example gdb simply call (on the correct host):
24  // gdb -pid PID
25  // you can continue the program by calling at the gdb prompt:
26  // > set var cont = 1
27  // > continue
28  int attach(int p=-1);
29  //
30  // dune_assert( bool ) or dune_assert( bool, p )
31  // This is a special assert like macro that allows a bit more flexibility
32  // then the standard assert. There are three different available
33  // behaviors of a failed dune_assert call:
34  // - If ASSERTATTACH is defined then attach is called with the optional
35  // process rank p, i.e., the assert is ignored except on the process
36  // with rank p.
37  // - If ASSERTATTACH is not defined but ASSERTCONTINUE then the assert
38  // message is printed but the program tries to continue regardless. This
39  // can be usefull for some unit tests
40  // - If neither ASSERTATTACH nor ASSERTCONTINUE is defined then the program
41  // will be aborted.
42  int attach(int p)
43  {
44  int cont = 0;
45  char hostname[256];
46  gethostname(hostname, sizeof(hostname));
47 #if HAVE_MPI
48  int mpirank = -1;
49  MPI_Comm_rank(MPI_COMM_WORLD,&mpirank);
50  if (p >= 0 && p != mpirank)
51  {
52  std::cout << "[" << mpirank << "] has PID " << getpid() << " on " << hostname << " continuing" << std::endl;
53  return 1;
54  }
55  else
56  std::cout << "[" << mpirank << "] has PID " << getpid() << " on " << hostname << " ready to attach" << std::endl;
57 #else
58  std::cout << "PID " << getpid() << " on " << hostname << " ready to attach" << std::endl;
59 #endif
60  while (0 == cont)
61  sleep(5);
62  return 1;
63  }
64 
65  // a handle for the dune_assert macro.
66  // The usual output from the C assert (including the mpi rank on a
67  // parallel run) is printed to std::cerr.
68  typedef int (*AssertHandler)(char const*, char const*, int);
69  int default_assert_handler(char const* expr, char const* file, int line)
70  {
71 #if HAVE_MPI
72  int mpirank = -1;
73  MPI_Comm_rank(MPI_COMM_WORLD,&mpirank);
74  std::cout << "[" << mpirank << "]: ";
75 #endif
76  std::cerr << "Assertion " << expr << " failed in " << file << ":" << line << std::endl;
77  return 1;
78  }
79  AssertHandler assert_handler = default_assert_handler;
80 }
81 
82 
83 // the ASSERT_HALT macro is available in three flavours depending on some
84 // defines:
85 #if defined(ASSERTATTACH)
86 #define ASSERT_HALT(p) attach(p)
87 #elif defined(ASSERTCONTINUE)
88 #define ASSERT_HALT(p) ((void)sizeof(p)), std::cout << "... trying to continue ..." << std::endl
89 #else
90 #define ASSERT_HALT(p) ((void)sizeof(p)), abort()
91 #endif
92 
93 // The actual implementation fo the dune_assert macro
94 #ifndef NDEBUG
95 #define dune_assert_(x,p) ((void)(!(x) && assert_handler(#x, __FILE__, __LINE__) && (ASSERT_HALT(p), 1)))
96 #else
97 #define dune_assert_(x,p) ((void)sizeof(x),sizeof(p))
98 #endif
99 
100 // Allow for calling dune_assert with one or two arguments
101 #define dune_assert0_(x) dune_assert_(x,-1)
102 #define dune_assert1_(x,p) dune_assert_(x,p)
103 #define GET_ASSERT_MACRO(_1,_2,NAME,...) NAME
104 #define dune_assert(...) GET_ASSERT_MACRO(__VA_ARGS__, dune_assert1_, dune_assert0_)(__VA_ARGS__)
105 
106 #endif