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
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
netstring.cpp networkstream.cpp object.cpp objectlock.cpp process.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;
pid_t Application::m_ReloadProcess = 0;
static bool l_Restarting = false;
static bool l_InExceptionHandler = false;
int Application::m_ArgC;
char **Application::m_ArgV;
double Application::m_StartTime;
@ -578,6 +579,12 @@ BOOL WINAPI Application::CtrlHandler(DWORD type)
*/
void Application::ExceptionHandler(void)
{
if (l_InExceptionHandler)
for (;;)
Utility::Sleep(5);
l_InExceptionHandler = true;
#ifndef _WIN32
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
@ -607,6 +614,11 @@ void Application::ExceptionHandler(void)
#ifdef _WIN32
LONG CALLBACK Application::SEHUnhandledExceptionFilter(PEXCEPTION_POINTERS exi)
{
if (l_InExceptionHandler)
return EXCEPTION_CONTINUE_SEARCH;
l_InExceptionHandler = true;
DisplayInfoMessage();
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. *
******************************************************************************/
#include "config/debuginfo.hpp"
#include "base/debuginfo.hpp"
#include "base/convert.hpp"
#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
#define DEBUGINFO_H
#include "config/i2-config.hpp"
#include "base/i2-base.hpp"
#include "base/qstring.hpp"
#include "base/exception.hpp"
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());
}
DebugInfo DynamicObject::GetDebugInfo(void) const
{
return m_DebugInfo;
}
void DynamicObject::SetDebugInfo(const DebugInfo& di)
{
m_DebugInfo = di;
}
bool DynamicObject::IsActive(void) const
{
return GetActive();

View File

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

View File

@ -21,6 +21,7 @@
#include "base/serializer.hpp"
#include "base/debug.hpp"
#include "base/objectlock.hpp"
#include "base/convert.hpp"
using namespace icinga;
@ -99,7 +100,9 @@ void DynamicType::RegisterObject(const DynamicObject::Ptr& object)
if (it->second == object)
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;

View File

@ -153,3 +153,18 @@ String icinga::DiagnosticInformation(boost::exception_ptr 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
{
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 void SetLastExceptionStack(const StackTrace& trace);

View File

@ -34,7 +34,7 @@ set(config_SOURCES
aexpression.cpp applyrule.cpp base-type.conf base-type.cpp
configcompilercontext.cpp configcompiler.cpp configerror.cpp configitembuilder.cpp
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)

View File

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

View File

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

View File

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

View File

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

View File

@ -23,21 +23,6 @@
using namespace icinga;
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
#include "config/i2-config.hpp"
#include "config/debuginfo.hpp"
#include "base/debuginfo.hpp"
#include "base/exception.hpp"
namespace icinga
@ -34,19 +34,8 @@ class I2_CONFIG_API ConfigError : virtual public user_error
{
public:
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 */

View File

@ -22,6 +22,7 @@
#include "config/applyrule.hpp"
#include "config/objectrule.hpp"
#include "config/configtype.hpp"
#include "config/configerror.hpp"
#include "base/application.hpp"
#include "base/dynamictype.hpp"
#include "base/objectlock.hpp"
@ -180,9 +181,6 @@ DynamicObject::Ptr ConfigItem::Commit(void)
if (!dtype)
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())
return DynamicObject::Ptr();
@ -195,6 +193,7 @@ DynamicObject::Ptr ConfigItem::Commit(void)
}
DynamicObject::Ptr dobj = dtype->CreateObject(properties);
dobj->SetDebugInfo(m_DebugInfo);
dobj->Register();
m_Object = dobj;

View File

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

View File

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

View File

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