From: Gunnar Beutner Date: Mon, 24 Aug 2015 09:04:26 +0000 (+0200) Subject: Remove the FutureExpression class X-Git-Tag: v2.4.0~385 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6a8f890e7c6ba8c311412c64879afb8a5cc84724;p=icinga2 Remove the FutureExpression class fixes #9972 --- diff --git a/doc/19-language-reference.md b/doc/19-language-reference.md index e7f039fbd..6c23c242a 100644 --- a/doc/19-language-reference.md +++ b/doc/19-language-reference.md @@ -783,6 +783,17 @@ The `continue` and `break` keywords can be used to control how the loop is execu skips over the remaining expressions for the loop body and begins the next loop evaluation. The `break` keyword breaks out of the loop. +## Exceptions + +Built-in commands may throw exceptions to signal errors such as invalid arguments. User scripts can throw exceptions +using the `throw` keyword. + +Example: + + throw "An error occurred." + +There is currently no way for scripts to catch exceptions. + ## Types All values have a static type. The `typeof` function can be used to determine the type of a value: diff --git a/lib/config/config_lexer.ll b/lib/config/config_lexer.ll index 9455eb1b4..f03ea8e83 100644 --- a/lib/config/config_lexer.ll +++ b/lib/config/config_lexer.ll @@ -196,6 +196,7 @@ for return T_FOR; if return T_IF; else return T_ELSE; while return T_WHILE; +throw return T_THROW; =\> return T_FOLLOWS; \<\< return T_SHIFT_LEFT; \>\> return T_SHIFT_RIGHT; diff --git a/lib/config/config_parser.yy b/lib/config/config_parser.yy index f713aefad..f23b377be 100644 --- a/lib/config/config_parser.yy +++ b/lib/config/config_parser.yy @@ -165,6 +165,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig %token T_IF "if (T_IF)" %token T_ELSE "else (T_ELSE)" %token T_WHILE "while (T_WHILE)" +%token T_THROW "throw (T_THROW)" %token T_FOLLOWS "=> (T_FOLLOWS)" %token T_NULLARY_LAMBDA_BEGIN "{{ (T_NULLARY_LAMBDA_BEGIN)" %token T_NULLARY_LAMBDA_END "}} (T_NULLARY_LAMBDA_END)" @@ -566,6 +567,10 @@ lterm: library $$ = new WhileExpression($3, $5, @$); } + | T_THROW rterm + { + $$ = new ThrowExpression($2, @$); + } | rterm_side_effect ; diff --git a/lib/config/configcompiler.cpp b/lib/config/configcompiler.cpp index b678b735d..a9f99d485 100644 --- a/lib/config/configcompiler.cpp +++ b/lib/config/configcompiler.cpp @@ -54,7 +54,6 @@ ConfigCompiler::ConfigCompiler(const String& path, std::istream *input, ConfigCompiler::~ConfigCompiler(void) { DestroyScanner(); - delete m_Input; } /** @@ -227,17 +226,6 @@ void ConfigCompiler::HandleLibrary(const String& library) Loader::LoadExtensionLibrary(library); } -void ConfigCompiler::CompileHelper(void) -{ - try { - m_Promise.set_value(boost::shared_ptr(Compile())); - } catch (...) { - m_Promise.set_exception(boost::current_exception()); - } - - delete this; -} - /** * Compiles a stream. * @@ -252,25 +240,14 @@ Expression *ConfigCompiler::CompileStream(const String& path, stream->exceptions(std::istream::badbit); - ConfigCompiler* ctx = new ConfigCompiler(path, stream, zone, module); + ConfigCompiler ctx(path, stream, zone, module); - if (async) { - boost::shared_future > ftr = boost::shared_future >(ctx->m_Promise.get_future()); - - Utility::QueueAsyncCallback(boost::bind(&ConfigCompiler::CompileHelper, ctx)); - return new FutureExpression(ftr); - } else { - Expression *expr; - - try { - expr = ctx->Compile(); - } catch (...) { - delete ctx; - throw; - } - - delete ctx; - return expr; + try { + return ctx.Compile(); + } catch (const ScriptError& ex) { + return new ThrowExpression(MakeLiteral(ex.what()), ex.GetDebugInfo()); + } catch (const std::exception& ex) { + return new ThrowExpression(MakeLiteral(DiagnosticInformation(ex))); } } @@ -285,10 +262,9 @@ Expression *ConfigCompiler::CompileFile(const String& path, bool async, { CONTEXT("Compiling configuration file '" + path + "'"); - std::ifstream *stream = new std::ifstream(); - stream->open(path.CStr(), std::ifstream::in); + std::ifstream stream(path.CStr(), std::ifstream::in); - if (!*stream) + if (!stream) BOOST_THROW_EXCEPTION(posix_error() << boost::errinfo_api_function("std::ifstream::open") << boost::errinfo_errno(errno) @@ -297,7 +273,7 @@ Expression *ConfigCompiler::CompileFile(const String& path, bool async, Log(LogInformation, "ConfigCompiler") << "Compiling config file: " << path; - return CompileStream(path, stream, async, zone, module); + return CompileStream(path, &stream, async, zone, module); } /** @@ -310,8 +286,8 @@ Expression *ConfigCompiler::CompileFile(const String& path, bool async, Expression *ConfigCompiler::CompileText(const String& path, const String& text, bool async, const String& zone, const String& module) { - std::stringstream *stream = new std::stringstream(text); - return CompileStream(path, stream, async, zone, module); + std::stringstream stream(text); + return CompileStream(path, &stream, async, zone, module); } /** @@ -378,6 +354,7 @@ const std::vector& ConfigCompiler::GetKeywords(void) keywords.push_back("if"); keywords.push_back("else"); keywords.push_back("while"); + keywords.push_back("throw"); } return keywords; diff --git a/lib/config/configcompiler.hpp b/lib/config/configcompiler.hpp index d1513a24d..3a9a08257 100644 --- a/lib/config/configcompiler.hpp +++ b/lib/config/configcompiler.hpp @@ -135,8 +135,6 @@ private: void InitializeScanner(void); void DestroyScanner(void); - void CompileHelper(void); - void HandleIncludeZone(const String& tag, const String& path, const String& pattern, std::vector& expressions); public: diff --git a/lib/config/expression.cpp b/lib/config/expression.cpp index 65d910bcc..58a65de77 100644 --- a/lib/config/expression.cpp +++ b/lib/config/expression.cpp @@ -702,6 +702,14 @@ void icinga::BindToScope(Expression *& expr, ScopeSpecifier scopeSpec) } } +ExpressionResult ThrowExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const +{ + ExpressionResult messageres = m_Message->Evaluate(frame); + CHECK_RESULT(messageres); + Value message = messageres.GetValue(); + BOOST_THROW_EXCEPTION(ScriptError(message, m_DebugInfo)); +} + ExpressionResult ImportExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const { if (frame.Sandboxed) diff --git a/lib/config/expression.hpp b/lib/config/expression.hpp index b4bb1eb6f..6c75e3cfc 100644 --- a/lib/config/expression.hpp +++ b/lib/config/expression.hpp @@ -224,28 +224,6 @@ private: boost::shared_ptr m_Expression; }; -class I2_CONFIG_API FutureExpression : public Expression -{ -public: - FutureExpression(const boost::shared_future >& future) - : m_Future(future) - { } - -protected: - virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override - { - return m_Future.get()->DoEvaluate(frame, dhint); - } - - virtual const DebugInfo& GetDebugInfo(void) const override - { - return m_Future.get()->GetDebugInfo(); - } - -private: - mutable boost::shared_future > m_Future; -}; - class I2_CONFIG_API LiteralExpression : public Expression { public: @@ -767,6 +745,25 @@ protected: I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec); +class I2_CONFIG_API ThrowExpression : public DebuggableExpression +{ +public: + ThrowExpression(Expression *message, const DebugInfo& debugInfo = DebugInfo()) + : DebuggableExpression(debugInfo), m_Message(message) + { } + + ~ThrowExpression(void) + { + delete m_Message; + } + +protected: + virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override; + +private: + Expression *m_Message; +}; + class I2_CONFIG_API ImportExpression : public DebuggableExpression { public: