mirror of
				https://github.com/Icinga/icinga2.git
				synced 2025-11-03 21:25:56 +01:00 
			
		
		
		
	Implement automated stacktraces for exceptions.
This commit is contained in:
		
							parent
							
								
									e2416b5b54
								
							
						
					
					
						commit
						cada2abeb3
					
				@ -88,7 +88,7 @@ String CompatComponent::GetCommandPath(void) const
 | 
			
		||||
 | 
			
		||||
	Value commandPath = config->Get("command_path");
 | 
			
		||||
	if (commandPath.IsEmpty())
 | 
			
		||||
		return Application::GetLocalStateDir() + "/run/icinga/icinga2.cmd";
 | 
			
		||||
		return Application::GetLocalStateDir() + "/run/icinga2/icinga2.cmd";
 | 
			
		||||
	else
 | 
			
		||||
		return commandPath;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -83,12 +83,6 @@ else
 | 
			
		||||
fi
 | 
			
		||||
AC_MSG_RESULT($enable_debug)
 | 
			
		||||
 | 
			
		||||
AX_C___ATTRIBUTE__
 | 
			
		||||
if test "$ax_cv___attribute__" = "yes" && test "x$enable_debug" = "xno"; then
 | 
			
		||||
	CFLAGS="$CFLAGS -fvisibility=hidden"
 | 
			
		||||
	CXXFLAGS="$CXXFLAGS -fvisibility=hidden"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
AX_PYTHON_DEFAULT
 | 
			
		||||
AX_PYTHON_ENABLE
 | 
			
		||||
AX_PYTHON_VERSION_ENSURE([2.5])
 | 
			
		||||
 | 
			
		||||
@ -353,16 +353,24 @@ void Application::ExceptionHandler(void)
 | 
			
		||||
	sigaction(SIGABRT, &sa, NULL);
 | 
			
		||||
#endif /* _WIN32 */
 | 
			
		||||
 | 
			
		||||
	bool has_trace = false;
 | 
			
		||||
 | 
			
		||||
	try {
 | 
			
		||||
		throw;
 | 
			
		||||
	} catch (const std::exception& ex) {
 | 
			
		||||
		std::cerr << std::endl
 | 
			
		||||
			  << diagnostic_information(ex)
 | 
			
		||||
			  << std::endl;
 | 
			
		||||
 | 
			
		||||
		has_trace = (boost::get_error_info<StackTraceErrorInfo>(ex) != NULL);
 | 
			
		||||
	} catch (...) {
 | 
			
		||||
		std::cerr << "Exception of unknown type." << std::endl;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!has_trace) {
 | 
			
		||||
		StackTrace trace;
 | 
			
		||||
		trace.Print(std::cerr, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DisplayBugMessage();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,8 @@
 | 
			
		||||
 | 
			
		||||
using namespace icinga;
 | 
			
		||||
 | 
			
		||||
StackTrace *Exception::m_StackTrace = NULL;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieves the error code for the exception.
 | 
			
		||||
 *
 | 
			
		||||
@ -125,3 +127,47 @@ String OpenSSLException::FormatErrorCode(int code)
 | 
			
		||||
 | 
			
		||||
	return message;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef _WIN32
 | 
			
		||||
extern "C"
 | 
			
		||||
void __cxa_throw(void *obj, void *pvtinfo, void (*dest)(void *))
 | 
			
		||||
{
 | 
			
		||||
	typedef void (*cxa_throw_fn)(void *, void *, void (*) (void *)) __attribute__((noreturn));
 | 
			
		||||
	static cxa_throw_fn real_cxa_throw;
 | 
			
		||||
 | 
			
		||||
	if (real_cxa_throw == 0)
 | 
			
		||||
		real_cxa_throw = (cxa_throw_fn)dlsym(RTLD_NEXT, "__cxa_throw");
 | 
			
		||||
 | 
			
		||||
	void *thrown_ptr = obj;
 | 
			
		||||
	const type_info *tinfo = static_cast<type_info *>(pvtinfo);
 | 
			
		||||
	const type_info *boost_exc = &typeid(boost::exception);
 | 
			
		||||
 | 
			
		||||
	/* Check if the exception is a pointer type. */
 | 
			
		||||
	if (tinfo->__is_pointer_p())
 | 
			
		||||
		thrown_ptr = *(void **)thrown_ptr;
 | 
			
		||||
 | 
			
		||||
	/* Check if thrown_ptr inherits from boost::exception. */
 | 
			
		||||
	if (boost_exc->__do_catch(tinfo, &thrown_ptr, 1)) {
 | 
			
		||||
		boost::exception *ex = (boost::exception *)thrown_ptr;
 | 
			
		||||
 | 
			
		||||
		StackTrace trace;
 | 
			
		||||
		*ex << StackTraceErrorInfo(trace);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	real_cxa_throw(obj, pvtinfo, dest);
 | 
			
		||||
}
 | 
			
		||||
#endif /* _WIN32 */
 | 
			
		||||
 | 
			
		||||
StackTrace *Exception::GetLastStackTrace(void)
 | 
			
		||||
{
 | 
			
		||||
	return m_StackTrace;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Exception::SetLastStackTrace(const StackTrace& trace)
 | 
			
		||||
{
 | 
			
		||||
	if (m_StackTrace)
 | 
			
		||||
		delete m_StackTrace;
 | 
			
		||||
 | 
			
		||||
	m_StackTrace = new StackTrace(trace);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -54,6 +54,9 @@ public:
 | 
			
		||||
 | 
			
		||||
	virtual const char *what(void) const throw();
 | 
			
		||||
 | 
			
		||||
	static StackTrace *GetLastStackTrace(void);
 | 
			
		||||
	static void SetLastStackTrace(const StackTrace& trace);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	void SetCode(int code);
 | 
			
		||||
	void SetMessage(String message);
 | 
			
		||||
@ -61,8 +64,12 @@ protected:
 | 
			
		||||
private:
 | 
			
		||||
	String m_Message;
 | 
			
		||||
	int m_Code;
 | 
			
		||||
 | 
			
		||||
	static StackTrace *m_StackTrace;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef boost::error_info<StackTrace, StackTrace> StackTraceErrorInfo;
 | 
			
		||||
 | 
			
		||||
#define DEFINE_EXCEPTION_CLASS(klass)					\
 | 
			
		||||
	class klass : public Exception					\
 | 
			
		||||
	{								\
 | 
			
		||||
 | 
			
		||||
@ -102,7 +102,7 @@ void StackTrace::Initialize(void)
 | 
			
		||||
 *		       the one this function is executing in).
 | 
			
		||||
 * @returns true if the stacktrace was printed, false otherwise.
 | 
			
		||||
 */
 | 
			
		||||
void StackTrace::Print(ostream& fp, int ignoreFrames)
 | 
			
		||||
void StackTrace::Print(ostream& fp, int ignoreFrames) const
 | 
			
		||||
{
 | 
			
		||||
	fp << std::endl << "Stacktrace:" << std::endl;
 | 
			
		||||
 | 
			
		||||
@ -170,3 +170,9 @@ void StackTrace::Print(ostream& fp, int ignoreFrames)
 | 
			
		||||
	}
 | 
			
		||||
#endif /* _WIN32 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ostream& icinga::operator<<(ostream& stream, const StackTrace& trace)
 | 
			
		||||
{
 | 
			
		||||
	trace.Print(stream, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,7 @@ public:
 | 
			
		||||
	StackTrace(PEXCEPTION_POINTERS exi);
 | 
			
		||||
#endif /* _WIN32 */
 | 
			
		||||
 | 
			
		||||
	void Print(ostream& fp, int ignoreFrames = 0);
 | 
			
		||||
	void Print(ostream& fp, int ignoreFrames = 0) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	void *m_Frames[64];
 | 
			
		||||
@ -47,6 +47,8 @@ private:
 | 
			
		||||
	static void Initialize(void);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
I2_BASE_API ostream& operator<<(ostream& stream, const StackTrace& trace);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* UTILITY_H */
 | 
			
		||||
 | 
			
		||||
@ -37,6 +37,7 @@
 | 
			
		||||
#include <poll.h>
 | 
			
		||||
#include <glob.h>
 | 
			
		||||
#include <ltdl.h>
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
 | 
			
		||||
typedef int SOCKET;
 | 
			
		||||
#define INVALID_SOCKET (-1)
 | 
			
		||||
 | 
			
		||||
@ -1,66 +0,0 @@
 | 
			
		||||
# ===========================================================================
 | 
			
		||||
#    http://www.gnu.org/software/autoconf-archive/ax_c___attribute__.html
 | 
			
		||||
# ===========================================================================
 | 
			
		||||
#
 | 
			
		||||
# SYNOPSIS
 | 
			
		||||
#
 | 
			
		||||
#   AX_C___ATTRIBUTE__
 | 
			
		||||
#
 | 
			
		||||
# DESCRIPTION
 | 
			
		||||
#
 | 
			
		||||
#   Provides a test for the compiler support of __attribute__ extensions.
 | 
			
		||||
#   Defines HAVE___ATTRIBUTE__ if it is found.
 | 
			
		||||
#
 | 
			
		||||
# LICENSE
 | 
			
		||||
#
 | 
			
		||||
#   Copyright (c) 2008 Stepan Kasal <skasal@redhat.com>
 | 
			
		||||
#   Copyright (c) 2008 Christian Haggstrom
 | 
			
		||||
#   Copyright (c) 2008 Ryan McCabe <ryan@numb.org>
 | 
			
		||||
#
 | 
			
		||||
#   This program is free software; you can redistribute it and/or modify it
 | 
			
		||||
#   under the terms of the GNU General Public License as published by the
 | 
			
		||||
#   Free Software Foundation; either version 2 of the License, or (at your
 | 
			
		||||
#   option) any later version.
 | 
			
		||||
#
 | 
			
		||||
#   This program is distributed in the hope that it will be useful, but
 | 
			
		||||
#   WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 | 
			
		||||
#   Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
#   You should have received a copy of the GNU General Public License along
 | 
			
		||||
#   with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
#
 | 
			
		||||
#   As a special exception, the respective Autoconf Macro's copyright owner
 | 
			
		||||
#   gives unlimited permission to copy, distribute and modify the configure
 | 
			
		||||
#   scripts that are the output of Autoconf when processing the Macro. You
 | 
			
		||||
#   need not follow the terms of the GNU General Public License when using
 | 
			
		||||
#   or distributing such scripts, even though portions of the text of the
 | 
			
		||||
#   Macro appear in them. The GNU General Public License (GPL) does govern
 | 
			
		||||
#   all other use of the material that constitutes the Autoconf Macro.
 | 
			
		||||
#
 | 
			
		||||
#   This special exception to the GPL applies to versions of the Autoconf
 | 
			
		||||
#   Macro released by the Autoconf Archive. When you make and distribute a
 | 
			
		||||
#   modified version of the Autoconf Macro, you may extend this special
 | 
			
		||||
#   exception to the GPL to apply to your modified version as well.
 | 
			
		||||
 | 
			
		||||
#serial 8
 | 
			
		||||
 | 
			
		||||
AC_DEFUN([AX_C___ATTRIBUTE__], [
 | 
			
		||||
  AC_CACHE_CHECK([for __attribute__], [ax_cv___attribute__],
 | 
			
		||||
    [AC_COMPILE_IFELSE(
 | 
			
		||||
      [AC_LANG_PROGRAM(
 | 
			
		||||
	[[#include <stdlib.h>
 | 
			
		||||
	  static void foo(void) __attribute__ ((unused));
 | 
			
		||||
	  static void
 | 
			
		||||
	  foo(void) {
 | 
			
		||||
	      exit(1);
 | 
			
		||||
	  }
 | 
			
		||||
        ]], [])],
 | 
			
		||||
      [ax_cv___attribute__=yes],
 | 
			
		||||
      [ax_cv___attribute__=no]
 | 
			
		||||
    )
 | 
			
		||||
  ])
 | 
			
		||||
  if test "$ax_cv___attribute__" = "yes"; then
 | 
			
		||||
    AC_DEFINE([HAVE___ATTRIBUTE__], 1, [define if your compiler has __attribute__])
 | 
			
		||||
  fi
 | 
			
		||||
])
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user