Improve error message for duplicate objects

refs #6070
This commit is contained in:
Gunnar Beutner 2014-09-09 14:49:21 +02:00
parent 292d9ee740
commit 308ba45102
20 changed files with 91 additions and 47 deletions

View File

@ -24,7 +24,7 @@ mkclass_target(sysloglogger.ti sysloglogger.thpp)
set(base_SOURCES set(base_SOURCES
application.cpp application.thpp array.cpp context.cpp application.cpp application.thpp array.cpp context.cpp
convert.cpp dictionary.cpp dynamicobject.cpp dynamicobject.thpp dynamictype.cpp convert.cpp debuginfo.cpp dictionary.cpp dynamicobject.cpp dynamicobject.thpp dynamictype.cpp
exception.cpp fifo.cpp filelogger.cpp filelogger.thpp logger.cpp logger.thpp exception.cpp fifo.cpp filelogger.cpp filelogger.thpp logger.cpp logger.thpp
netstring.cpp networkstream.cpp object.cpp objectlock.cpp process.cpp netstring.cpp networkstream.cpp object.cpp objectlock.cpp process.cpp
qstring.cpp ringbuffer.cpp scriptfunction.cpp scriptfunctionwrapper.cpp qstring.cpp ringbuffer.cpp scriptfunction.cpp scriptfunctionwrapper.cpp

View File

@ -50,6 +50,7 @@ bool Application::m_RequestRestart = false;
bool Application::m_RequestReopenLogs = false; bool Application::m_RequestReopenLogs = false;
pid_t Application::m_ReloadProcess = 0; pid_t Application::m_ReloadProcess = 0;
static bool l_Restarting = false; static bool l_Restarting = false;
static bool l_InExceptionHandler = false;
int Application::m_ArgC; int Application::m_ArgC;
char **Application::m_ArgV; char **Application::m_ArgV;
double Application::m_StartTime; double Application::m_StartTime;
@ -578,6 +579,12 @@ BOOL WINAPI Application::CtrlHandler(DWORD type)
*/ */
void Application::ExceptionHandler(void) void Application::ExceptionHandler(void)
{ {
if (l_InExceptionHandler)
for (;;)
Utility::Sleep(5);
l_InExceptionHandler = true;
#ifndef _WIN32 #ifndef _WIN32
struct sigaction sa; struct sigaction sa;
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
@ -607,6 +614,11 @@ void Application::ExceptionHandler(void)
#ifdef _WIN32 #ifdef _WIN32
LONG CALLBACK Application::SEHUnhandledExceptionFilter(PEXCEPTION_POINTERS exi) LONG CALLBACK Application::SEHUnhandledExceptionFilter(PEXCEPTION_POINTERS exi)
{ {
if (l_InExceptionHandler)
return EXCEPTION_CONTINUE_SEARCH;
l_InExceptionHandler = true;
DisplayInfoMessage(); DisplayInfoMessage();
std::cerr << "Caught unhandled SEH exception." << std::endl std::cerr << "Caught unhandled SEH exception." << std::endl

View File

@ -17,7 +17,7 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/ ******************************************************************************/
#include "config/debuginfo.hpp" #include "base/debuginfo.hpp"
#include "base/convert.hpp" #include "base/convert.hpp"
#include <fstream> #include <fstream>
@ -107,3 +107,12 @@ void icinga::ShowCodeFragment(std::ostream& out, const DebugInfo& di, bool verbo
} }
} }
} }
std::string icinga::to_string(const errinfo_debuginfo& e)
{
std::ostringstream msgbuf;
msgbuf << "Config location: " << e.value() << "\n";
ShowCodeFragment(msgbuf, e.value(), true);
return msgbuf.str();
}

View File

@ -20,8 +20,9 @@
#ifndef DEBUGINFO_H #ifndef DEBUGINFO_H
#define DEBUGINFO_H #define DEBUGINFO_H
#include "config/i2-config.hpp" #include "base/i2-base.hpp"
#include "base/qstring.hpp" #include "base/qstring.hpp"
#include "base/exception.hpp"
namespace icinga namespace icinga
{ {
@ -60,11 +61,16 @@ struct DebugInfo
}; };
}; };
I2_CONFIG_API std::ostream& operator<<(std::ostream& out, const DebugInfo& val); I2_BASE_API std::ostream& operator<<(std::ostream& out, const DebugInfo& val);
I2_CONFIG_API DebugInfo DebugInfoRange(const DebugInfo& start, const DebugInfo& end); I2_BASE_API DebugInfo DebugInfoRange(const DebugInfo& start, const DebugInfo& end);
I2_CONFIG_API void ShowCodeFragment(std::ostream& out, const DebugInfo& di, bool verbose); I2_BASE_API void ShowCodeFragment(std::ostream& out, const DebugInfo& di, bool verbose);
struct errinfo_debuginfo_;
typedef boost::error_info<struct errinfo_debuginfo_, DebugInfo> errinfo_debuginfo;
std::string to_string(const errinfo_debuginfo& e);
} }

View File

@ -54,6 +54,16 @@ DynamicType::Ptr DynamicObject::GetType(void) const
return DynamicType::GetByName(GetTypeName()); return DynamicType::GetByName(GetTypeName());
} }
DebugInfo DynamicObject::GetDebugInfo(void) const
{
return m_DebugInfo;
}
void DynamicObject::SetDebugInfo(const DebugInfo& di)
{
m_DebugInfo = di;
}
bool DynamicObject::IsActive(void) const bool DynamicObject::IsActive(void) const
{ {
return GetActive(); return GetActive();

View File

@ -25,6 +25,7 @@
#include "base/object.hpp" #include "base/object.hpp"
#include "base/serializer.hpp" #include "base/serializer.hpp"
#include "base/dictionary.hpp" #include "base/dictionary.hpp"
#include "base/debuginfo.hpp"
#include <boost/signals2.hpp> #include <boost/signals2.hpp>
#include <map> #include <map>
@ -53,6 +54,9 @@ public:
shared_ptr<DynamicType> GetType(void) const; shared_ptr<DynamicType> GetType(void) const;
DebugInfo GetDebugInfo(void) const;
void SetDebugInfo(const DebugInfo& di);
bool IsActive(void) const; bool IsActive(void) const;
bool IsPaused(void) const; bool IsPaused(void) const;
@ -93,6 +97,8 @@ protected:
private: private:
static DynamicObject::Ptr GetObject(const String& type, const String& name); static DynamicObject::Ptr GetObject(const String& type, const String& name);
static void RestoreObject(const String& message, int attributeTypes); static void RestoreObject(const String& message, int attributeTypes);
DebugInfo m_DebugInfo;
}; };
#define DECLARE_TYPENAME(klass) \ #define DECLARE_TYPENAME(klass) \

View File

@ -21,6 +21,7 @@
#include "base/serializer.hpp" #include "base/serializer.hpp"
#include "base/debug.hpp" #include "base/debug.hpp"
#include "base/objectlock.hpp" #include "base/objectlock.hpp"
#include "base/convert.hpp"
using namespace icinga; using namespace icinga;
@ -99,7 +100,9 @@ void DynamicType::RegisterObject(const DynamicObject::Ptr& object)
if (it->second == object) if (it->second == object)
return; return;
BOOST_THROW_EXCEPTION(std::runtime_error("RegisterObject() found existing object with the same name: " + name)); BOOST_THROW_EXCEPTION(user_error("An object with type '" + m_Name + "' and name '" + name + "' already exists (" +
Convert::ToString(it->second->GetDebugInfo()) + "), new declaration: " + Convert::ToString(object->GetDebugInfo()))
<< errinfo_debuginfo(object->GetDebugInfo()));
} }
m_ObjectMap[name] = object; m_ObjectMap[name] = object;

View File

@ -153,3 +153,18 @@ String icinga::DiagnosticInformation(boost::exception_ptr eptr)
return boost::diagnostic_information(eptr); return boost::diagnostic_information(eptr);
} }
user_error::user_error(void)
{ }
user_error::user_error(const String& message)
: m_Message(message)
{ }
user_error::~user_error(void) throw()
{ }
const char *user_error::what(void) const throw()
{
return m_Message.CStr();
}

View File

@ -38,7 +38,17 @@
namespace icinga namespace icinga
{ {
class I2_BASE_API user_error : virtual public std::exception, virtual public boost::exception { }; class I2_BASE_API user_error : virtual public std::exception, virtual public boost::exception {
public:
user_error(void);
user_error(const String& message);
~user_error(void) throw();
const char *what(void) const throw();
private:
String m_Message;
};
I2_BASE_API StackTrace *GetLastExceptionStack(void); I2_BASE_API StackTrace *GetLastExceptionStack(void);
I2_BASE_API void SetLastExceptionStack(const StackTrace& trace); I2_BASE_API void SetLastExceptionStack(const StackTrace& trace);

View File

@ -34,7 +34,7 @@ set(config_SOURCES
aexpression.cpp applyrule.cpp base-type.conf base-type.cpp aexpression.cpp applyrule.cpp base-type.conf base-type.cpp
configcompilercontext.cpp configcompiler.cpp configerror.cpp configitembuilder.cpp configcompilercontext.cpp configcompiler.cpp configerror.cpp configitembuilder.cpp
configitem.cpp ${FLEX_config_lexer_OUTPUTS} ${BISON_config_parser_OUTPUTS} configitem.cpp ${FLEX_config_lexer_OUTPUTS} ${BISON_config_parser_OUTPUTS}
configtype.cpp debuginfo.cpp objectrule.cpp typerule.cpp typerulelist.cpp configtype.cpp objectrule.cpp typerule.cpp typerulelist.cpp
) )
if(ICINGA2_UNITY_BUILD) if(ICINGA2_UNITY_BUILD)

View File

@ -21,7 +21,7 @@
#define AEXPRESSION_H #define AEXPRESSION_H
#include "config/i2-config.hpp" #include "config/i2-config.hpp"
#include "config/debuginfo.hpp" #include "base/debuginfo.hpp"
#include "base/array.hpp" #include "base/array.hpp"
#include "base/dictionary.hpp" #include "base/dictionary.hpp"

View File

@ -22,7 +22,7 @@
#include "config/i2-config.hpp" #include "config/i2-config.hpp"
#include "config/aexpression.hpp" #include "config/aexpression.hpp"
#include "config/debuginfo.hpp" #include "base/debuginfo.hpp"
#include <boost/function.hpp> #include <boost/function.hpp>
namespace icinga namespace icinga

View File

@ -21,7 +21,7 @@
#define CONFIGCOMPILER_H #define CONFIGCOMPILER_H
#include "config/i2-config.hpp" #include "config/i2-config.hpp"
#include "config/debuginfo.hpp" #include "base/debuginfo.hpp"
#include "base/registry.hpp" #include "base/registry.hpp"
#include "base/initialize.hpp" #include "base/initialize.hpp"
#include "base/singleton.hpp" #include "base/singleton.hpp"

View File

@ -21,7 +21,7 @@
#define CONFIGCOMPILERCONTEXT_H #define CONFIGCOMPILERCONTEXT_H
#include "config/i2-config.hpp" #include "config/i2-config.hpp"
#include "config/debuginfo.hpp" #include "base/debuginfo.hpp"
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <vector> #include <vector>

View File

@ -23,21 +23,6 @@
using namespace icinga; using namespace icinga;
ConfigError::ConfigError(const String& message) ConfigError::ConfigError(const String& message)
: m_Message(message) : user_error(message)
{ } { }
ConfigError::~ConfigError(void) throw()
{ }
const char *ConfigError::what(void) const throw()
{
return m_Message.CStr();
}
std::string icinga::to_string(const errinfo_debuginfo& e)
{
std::ostringstream msgbuf;
msgbuf << "Config location: " << e.value() << "\n";
ShowCodeFragment(msgbuf, e.value(), true);
return msgbuf.str();
}

View File

@ -21,7 +21,7 @@
#define CONFIGERROR_H #define CONFIGERROR_H
#include "config/i2-config.hpp" #include "config/i2-config.hpp"
#include "config/debuginfo.hpp" #include "base/debuginfo.hpp"
#include "base/exception.hpp" #include "base/exception.hpp"
namespace icinga namespace icinga
@ -34,19 +34,8 @@ class I2_CONFIG_API ConfigError : virtual public user_error
{ {
public: public:
ConfigError(const String& message); ConfigError(const String& message);
~ConfigError(void) throw();
const char *what(void) const throw();
private:
String m_Message;
}; };
struct errinfo_debuginfo_;
typedef boost::error_info<struct errinfo_debuginfo_, DebugInfo> errinfo_debuginfo;
std::string to_string(const errinfo_debuginfo& e);
} }
#endif /* CONFIGERROR_H */ #endif /* CONFIGERROR_H */

View File

@ -22,6 +22,7 @@
#include "config/applyrule.hpp" #include "config/applyrule.hpp"
#include "config/objectrule.hpp" #include "config/objectrule.hpp"
#include "config/configtype.hpp" #include "config/configtype.hpp"
#include "config/configerror.hpp"
#include "base/application.hpp" #include "base/application.hpp"
#include "base/dynamictype.hpp" #include "base/dynamictype.hpp"
#include "base/objectlock.hpp" #include "base/objectlock.hpp"
@ -180,9 +181,6 @@ DynamicObject::Ptr ConfigItem::Commit(void)
if (!dtype) if (!dtype)
BOOST_THROW_EXCEPTION(std::runtime_error("Type '" + GetType() + "' does not exist.")); BOOST_THROW_EXCEPTION(std::runtime_error("Type '" + GetType() + "' does not exist."));
if (dtype->GetObject(GetName()))
BOOST_THROW_EXCEPTION(std::runtime_error("An object with type '" + GetType() + "' and name '" + GetName() + "' already exists."));
if (IsAbstract()) if (IsAbstract())
return DynamicObject::Ptr(); return DynamicObject::Ptr();
@ -195,6 +193,7 @@ DynamicObject::Ptr ConfigItem::Commit(void)
} }
DynamicObject::Ptr dobj = dtype->CreateObject(properties); DynamicObject::Ptr dobj = dtype->CreateObject(properties);
dobj->SetDebugInfo(m_DebugInfo);
dobj->Register(); dobj->Register();
m_Object = dobj; m_Object = dobj;

View File

@ -20,9 +20,9 @@
#ifndef CONFIGITEMBUILDER_H #ifndef CONFIGITEMBUILDER_H
#define CONFIGITEMBUILDER_H #define CONFIGITEMBUILDER_H
#include "config/debuginfo.hpp"
#include "config/aexpression.hpp" #include "config/aexpression.hpp"
#include "config/configitem.hpp" #include "config/configitem.hpp"
#include "base/debuginfo.hpp"
#include "base/object.hpp" #include "base/object.hpp"
namespace icinga namespace icinga

View File

@ -22,7 +22,7 @@
#include "config/i2-config.hpp" #include "config/i2-config.hpp"
#include "config/aexpression.hpp" #include "config/aexpression.hpp"
#include "config/debuginfo.hpp" #include "base/debuginfo.hpp"
#include "base/dynamictype.hpp" #include "base/dynamictype.hpp"
namespace icinga namespace icinga

View File

@ -22,7 +22,7 @@
#include "config/i2-config.hpp" #include "config/i2-config.hpp"
#include "config/typerulelist.hpp" #include "config/typerulelist.hpp"
#include "config/debuginfo.hpp" #include "base/debuginfo.hpp"
namespace icinga namespace icinga
{ {