MercuryDPM  Alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Logger.cc
Go to the documentation of this file.
1 //Copyright (c) 2013-2014, The MercuryDPM Developers Team. All rights reserved.
2 //For the list of developers, see <http://www.MercuryDPM.org/Team>.
3 //
4 //Redistribution and use in source and binary forms, with or without
5 //modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name MercuryDPM nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 //WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 //DISCLAIMED. IN NO EVENT SHALL THE MERCURYDPM DEVELOPERS TEAM BE LIABLE FOR ANY
19 //DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 //(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 //ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 //(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 #include "Logger.h"
27 
28 #ifdef MERCURY_STACKTRACE_SHOW
29 //To create stacktraces, we need the
30 // backtrace(3)
31 //function calls.. (really, we don't want to do this by hand)
32 #include <execinfo.h>
33 
34 #ifdef MERCURY_STACKTRACE_DEMANGLE
35 //However, we would end up with mangled function names...
36 //So, instead we'll use the abi::__cxa_demangle function call..
37 #include <cxxabi.h>
38 //Oh, and we really want to get the function names as well..
39 #include <dlfcn.h>
40 #endif
41 
42 #endif
43 #include <cstdlib>
44 #include <iostream>
45 #include <csignal>
46 /*
47  * We need these to actually exists. These are used as tags in the template metaprogramming for
48  * the Logger class.
49  */
57 
58 /* Actual definition of the default logger. */
59 Logger<MERCURY_LOGLEVEL> logger("MercuryKernel");
60 
61 
62 // Default implementation for logging basic information
63 static void printInfo(std::string module, std::string msg)
64 {
65  std::cout << msg << std::endl;
66 }
67 
68 // Default implementation for logging warnings / messages
69 static void printMessage(std::string module, std::string msg)
70 {
71  std::cout << "Module " << module << ":\n" << msg << std::endl;
72 }
73 
74 // Default implementation for logging errors / fatals
75 // [[noreturn]] indicates this function may not return
76 [[noreturn]] static void printError(std::string module, std::string msg)
77 {
78  std::cerr << "Module " << module << ":\n" << msg << std::endl;
79 #ifdef MERCURY_STACKTRACE_SHOW
80  std::cerr << "\n-----------------[Stack Trace]-----------------\n";
81 
82  void* stackBuffer[64]; //This should be enough for all purposes..
83  //First, we retrieve the addresses of the entire stack...
84  int nStackFrames = backtrace(stackBuffer, 64);
85 #ifndef MERCURY_STACKTRACE_DEMANGLE
86  //We don't have the demangling infra, so just use backtrace_symbols.
87  char** functionNames = backtrace_symbols(stackBuffer, nStackFrames);
88  for( int i = 0; i < nStackFrames; i++ )
89  {
90  std::cerr << '\t' << functionNames[i] << '\n';
91  }
92  std::cerr << "Exiting.\n" << std::endl;
93 
94  //DO NOT USE DELETE HERE. THIS SHOULD BE free()'d!
95  // -- dducks
96  free(functionNames);
97 #else
98  //We request the symbol information ourselves, in order to be able to demangle it.
99  //And request the function names using dladdr.
100  Dl_info infoStruct;
101  for (int i = 4; i < nStackFrames; i++)
102  {
103  if (dladdr(stackBuffer[i], &infoStruct))
104  { // We succesfully loaded the address...
105  int demangleStatus;
106  char* fnDemangled = abi::__cxa_demangle(infoStruct.dli_sname, NULL, NULL, &demangleStatus);
107  if (infoStruct.dli_sname == nullptr)
108  continue;
109 
110  //We even succesfully demangled the symbol...
111  if (demangleStatus == 0)
112  {
113  std::cerr << fnDemangled << " +" << (void*) ((char*) stackBuffer[i] - (char*) infoStruct.dli_saddr) << "\t(" << infoStruct.dli_fname << ")\n";
114  free(fnDemangled);
115  }
116  else
117  { //Well, we tried. Lets output at least our raw symbol name.
118  std::cerr << infoStruct.dli_sname << " +" << (void*) ((char*) stackBuffer[i] - (char*) infoStruct.dli_saddr) << "\t(" << infoStruct.dli_fname << ")\n";
119  }
120  }
121  else
122  { //Name lookup failed.
123  std::cerr << stackBuffer[i] << ": ?????" << std::endl;
124  }
125  }
126 #endif
127 #endif
128  //send a signal first, in case a debugger can catch it
129  std::raise(SIGTERM);
130  std::exit(2);
131 }
132 
133 // Default output methods.
135  printError, //onError
136  printMessage, //onWarn
137  printInfo, //onInfo
138  printInfo, //onVerbose
139  printMessage //onDebug
140  };
141 
142 //And we assign them.
See How to use the logger for details on how to use the logger.
Definition: Logger.h:204
static void printError(std::string module, std::string msg)
Definition: Logger.cc:76
LL< Log::DEBUG > DEBUG
Debug information.
Definition: Logger.cc:56
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
LL< Log::INFO > INFO
Info log level.
Definition: Logger.cc:53
static void printInfo(std::string module, std::string msg)
Definition: Logger.cc:63
LoggerOutput loggerOutputDefaultImpl
Definition: Logger.cc:134
LL< Log::ERROR > ERROR
Error log level.
Definition: Logger.cc:51
LL< Log::WARN > WARN
Warning log level.
Definition: Logger.cc:52
static void printMessage(std::string module, std::string msg)
Definition: Logger.cc:69
Default functions for output generation.
Definition: Logger.h:182
LL< Log::DEFAULT > DEFAULT
Default log level.
Definition: Logger.cc:54
LL< Log::FATAL > FATAL
Fatal log level.
Definition: Logger.cc:50
LL< Log::VERBOSE > VERBOSE
Verbose information.
Definition: Logger.cc:55
LoggerOutput * loggerOutput
Declaration of the output functions. If the output needs to be redirected, please swap the loggerOutp...
Definition: Logger.cc:143
Tag for template metaprogramming.
Definition: Logger.h:216