[icinga-checkins] icinga.org: icinga2/master: Try to queue all PROCESS_FILE commands instead of exploding the stack

git at icinga.org git at icinga.org
Tue May 17 11:44:09 CEST 2016


Module: icinga2
Branch: master
Commit: 9f3a6b92a206effc5ec5922d315c608e800bf04a
URL:    https://git.icinga.org/?p=icinga2.git;a=commit;h=9f3a6b92a206effc5ec5922d315c608e800bf04a

Author: Vytenis Darulis <vytenis at uber.com>
Date:   Tue Oct 27 17:00:55 2015 +0000

Try to queue all PROCESS_FILE commands instead of exploding the stack

fixes #10426

Signed-off-by: Michael Friedrich <michael.friedrich at netways.de>

---

 lib/icinga/externalcommandprocessor.cpp |   84 ++++++++++++++++++++++++-------
 lib/icinga/externalcommandprocessor.hpp |    2 +
 2 files changed, 67 insertions(+), 19 deletions(-)

diff --git a/lib/icinga/externalcommandprocessor.cpp b/lib/icinga/externalcommandprocessor.cpp
index 09eeac2..b9f0479 100644
--- a/lib/icinga/externalcommandprocessor.cpp
+++ b/lib/icinga/externalcommandprocessor.cpp
@@ -290,6 +290,44 @@ void ExternalCommandProcessor::StaticInitialize(void)
 	RegisterCommand("DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS", &ExternalCommandProcessor::DisableServicegroupSvcNotifications, 1);
 }
 
+void ExternalCommandProcessor::ExecuteFromFile(const String& line, std::deque< std::vector<String> >& file_queue)
+{
+	if (line.IsEmpty())
+		return;
+
+	if (line[0] != '[')
+		BOOST_THROW_EXCEPTION(std::invalid_argument("Missing timestamp in command: " + line));
+
+	size_t pos = line.FindFirstOf("]");
+
+	if (pos == String::NPos)
+		BOOST_THROW_EXCEPTION(std::invalid_argument("Missing timestamp in command: " + line));
+
+	String timestamp = line.SubStr(1, pos - 1);
+	String args = line.SubStr(pos + 2, String::NPos);
+
+	double ts = Convert::ToDouble(timestamp);
+
+	if (ts == 0)
+		BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid timestamp in command: " + line));
+
+	std::vector<String> argv;
+	boost::algorithm::split(argv, args, boost::is_any_of(";"));
+
+	if (argv.empty())
+		BOOST_THROW_EXCEPTION(std::invalid_argument("Missing arguments in command: " + line));
+
+	std::vector<String> argvExtra(argv.begin() + 1, argv.end());
+
+	if (argv[0] == "PROCESS_FILE") {
+		Log(LogDebug, "ExternalCommandProcessor")
+			<< "Enqueing external command file " << argvExtra[0];
+		file_queue.push_back(argvExtra);
+	} else {
+		Execute(ts, argv[0], argvExtra);
+	}
+}
+
 void ExternalCommandProcessor::ProcessHostCheckResult(double time, const std::vector<String>& arguments)
 {
 	Host::Ptr host = Host::GetByName(arguments[0]);
@@ -897,33 +935,41 @@ void ExternalCommandProcessor::DisableHostgroupPassiveSvcChecks(double, const st
 
 void ExternalCommandProcessor::ProcessFile(double, const std::vector<String>& arguments)
 {
-	String file = arguments[0];
-	int del = Convert::ToLong(arguments[1]);
+	std::deque< std::vector<String> > file_queue;
+	file_queue.push_back(arguments);
 
-	std::ifstream ifp;
-	ifp.exceptions(std::ifstream::badbit);
+	while (!file_queue.empty()) {
+		std::vector<String> argument = file_queue.front();
+		file_queue.pop_front();
 
-	ifp.open(file.CStr(), std::ifstream::in);
+		String file = argument[0];
+		int to_delete = Convert::ToLong(argument[1]);
 
-	while (ifp.good()) {
-		std::string line;
-		std::getline(ifp, line);
+		std::ifstream ifp;
+		ifp.exceptions(std::ifstream::badbit);
 
-		try {
-			Log(LogNotice, "compat")
-			    << "Executing external command: " << line;
+		ifp.open(file.CStr(), std::ifstream::in);
 
-			Execute(line);
-		} catch (const std::exception& ex) {
-			Log(LogWarning, "ExternalCommandProcessor")
-			    << "External command failed: " << DiagnosticInformation(ex);
+		while (ifp.good()) {
+			std::string line;
+			std::getline(ifp, line);
+
+			try {
+				Log(LogNotice, "compat")
+				    << "Executing external command: " << line;
+
+				ExecuteFromFile(line, file_queue);
+			} catch (const std::exception& ex) {
+				Log(LogWarning, "ExternalCommandProcessor")
+				    << "External command failed: " << DiagnosticInformation(ex);
+			}
 		}
-	}
 
-	ifp.close();
+		ifp.close();
 
-	if (del > 0)
-		(void) unlink(file.CStr());
+		if (to_delete > 0)
+			(void) unlink(file.CStr());
+	}
 }
 
 void ExternalCommandProcessor::ScheduleSvcDowntime(double, const std::vector<String>& arguments)
diff --git a/lib/icinga/externalcommandprocessor.hpp b/lib/icinga/externalcommandprocessor.hpp
index 836b241..0596532 100644
--- a/lib/icinga/externalcommandprocessor.hpp
+++ b/lib/icinga/externalcommandprocessor.hpp
@@ -42,6 +42,8 @@ public:
 private:
 	ExternalCommandProcessor(void);
 
+	static void ExecuteFromFile(const String& line, std::deque< std::vector<String> >& file_queue);
+
 	static void ProcessHostCheckResult(double time, const std::vector<String>& arguments);
 	static void ProcessServiceCheckResult(double time, const std::vector<String>& arguments);
 	static void ScheduleHostCheck(double time, const std::vector<String>& arguments);



More information about the icinga-checkins mailing list