MFEM  v3.3.2
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
error.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 #include "error.hpp"
13 #include "globals.hpp"
14 #include "array.hpp"
15 #include <cstdlib>
16 #include <iostream>
17 
18 #ifdef MFEM_USE_LIBUNWIND
19 #define UNW_LOCAL_ONLY
20 #define UNW_NAME_LEN 512
21 #include <libunwind.h>
22 #include <cxxabi.h>
23 #if defined(__APPLE__) || defined(__linux__)
24 #ifndef _GNU_SOURCE
25 #define _GNU_SOURCE
26 #endif
27 #include <dlfcn.h>
28 #endif
29 #endif // MFEM_USE_LIBUNWIND
30 
31 #ifdef MFEM_USE_MPI
32 #include <mpi.h>
33 #endif
34 
35 namespace mfem
36 {
37 
38 void mfem_backtrace(int mode, int depth)
39 {
40 #ifdef MFEM_USE_LIBUNWIND
41  char name[UNW_NAME_LEN];
42  unw_cursor_t cursor;
43  unw_context_t uc;
44  unw_word_t ip, offp;
45 
46  int err = unw_getcontext(&uc);
47  err = err ? err : unw_init_local(&cursor, &uc);
48 
49  Array<unw_word_t> addrs;
50  while (unw_step(&cursor) > 0 && addrs.Size() != depth)
51  {
52  err = err ? err : unw_get_proc_name(&cursor, name, UNW_NAME_LEN, &offp);
53  err = err ? err : unw_get_reg(&cursor, UNW_REG_IP, &ip);
54  if (err) { break; }
55  char *name_p = name;
56  int demangle_status;
57 
58  // __cxa_demangle is not standard, but works with GCC, Intel, PGI, Clang
59  char *name_demangle =
60  abi::__cxa_demangle(name, NULL, NULL, &demangle_status);
61  if (demangle_status == 0) // use mangled name if something goes wrong
62  {
63  name_p = name_demangle;
64  }
65 
66  mfem::err << addrs.Size() << ") [0x" << std::hex << ip - 1 << std::dec
67  << "]: " << name_p << std::endl;
68  addrs.Append(ip - 1);
69 
70  if (demangle_status == 0)
71  {
72  free(name_demangle);
73  }
74  }
75 #if defined(__APPLE__) || defined(__linux__)
76  if (addrs.Size() > 0 && (mode & 1))
77  {
78  mfem::err << "\nLookup backtrace source lines:";
79  const char *fname = NULL;
80  for (int i = 0; i < addrs.Size(); i++)
81  {
82  Dl_info info;
83  err = !dladdr((void*)addrs[i], &info);
84  if (err)
85  {
86  fname = "<exe>";
87  }
88  else if (fname != info.dli_fname)
89  {
90  fname = info.dli_fname;
91  mfem::err << '\n';
92 #ifdef __linux__
93  mfem::err << "addr2line -C -e " << fname;
94 #else
95  mfem::err << "atos -o " << fname << " -l "
96  << (err ? 0 : info.dli_fbase);
97 #endif
98  }
99  mfem::err << " 0x" << std::hex << addrs[i] << std::dec;
100  }
101  mfem::err << '\n';
102  }
103 #endif
104 #endif // MFEM_USE_LIBUNWIND
105 }
106 
107 void mfem_error(const char *msg)
108 {
109  if (msg)
110  {
111  // NOTE: By default, each call of the "operator <<" method of the
112  // mfem::err object results in flushing the I/O stream, which can be a
113  // very bad thing if all your processors try to do it at the same time.
114  mfem::err << "\n\n" << msg << "\n";
115  }
116 
117 #ifdef MFEM_USE_LIBUNWIND
118  mfem::err << "Backtrace:" << std::endl;
119  mfem_backtrace(1, -1);
120  mfem::err << std::endl;
121 #endif
122 
123 #ifdef MFEM_USE_MPI
124  int init_flag, fin_flag;
125  MPI_Initialized(&init_flag);
126  MPI_Finalized(&fin_flag);
127  if (init_flag && !fin_flag) { MPI_Abort(GetGlobalMPI_Comm(), 1); }
128 #endif
129  std::abort(); // force crash by calling abort
130 }
131 
132 void mfem_warning(const char *msg)
133 {
134  if (msg)
135  {
136  mfem::out << "\n\n" << msg << std::endl;
137  }
138 }
139 
140 }
int Size() const
Logical size of the array.
Definition: array.hpp:110
void mfem_warning(const char *msg)
Definition: error.cpp:132
int Append(const T &el)
Append element to array, resize if necessary.
Definition: array.hpp:548
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
Definition: globals.hpp:69
void mfem_error(const char *msg)
Definition: error.cpp:107
void mfem_backtrace(int mode, int depth)
Definition: error.cpp:38
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:64
MPI_Comm GetGlobalMPI_Comm()
Get MFEM&#39;s &quot;global&quot; MPI communicator.
Definition: globals.cpp:27