]> granicus.if.org Git - icinga2/commitdiff
Implement command timeouts.
authorGunnar Beutner <gunnar.beutner@netways.de>
Thu, 13 Jun 2013 10:05:24 +0000 (12:05 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Thu, 13 Jun 2013 10:05:24 +0000 (12:05 +0200)
Fixes #2723

lib/base/process-unix.cpp
lib/base/process.cpp
lib/base/process.h
lib/icinga/icinga-type.conf
lib/icinga/pluginchecktask.cpp
lib/icinga/plugineventtask.cpp
lib/icinga/pluginnotificationtask.cpp

index 1b90a9eb611a348148c7514fb543d76606e48c73..d8b11f0bd3c4dffc72e76fde154adff0661f43ea 100644 (file)
@@ -32,6 +32,7 @@
 
 #ifndef _WIN32
 #include <execvpe.h>
+#include <poll.h>
 
 using namespace icinga;
 
@@ -158,13 +159,36 @@ ProcessResult Process::Run(void)
 
        std::ostringstream outputStream;
 
+       pollfd pfd;
+       pfd.fd = fd;
+       pfd.events = POLLIN;
+       pfd.revents = 0;
+
        for (;;) {
-               int rc = read(fd, buffer, sizeof(buffer));
+               int rc1, timeout;
+
+               timeout = 0;
+
+               if (m_Timeout != 0) {
+                       timeout = m_Timeout - (Utility::GetTime() - result.ExecutionStart);
+
+                       if (timeout < 0) {
+                               outputStream << "<Timeout exceeded.>";
+                               kill(m_Pid, SIGKILL);
+                               break;
+                       }
+               }
+
+               rc1 = poll(&pfd, 1, timeout * 1000);
 
-               if (rc <= 0)
-                       break;
+               if (rc1 > 0) {
+                       int rc2 = read(fd, buffer, sizeof(buffer));
 
-               outputStream.write(buffer, rc);
+                       if (rc2 <= 0)
+                               break;
+
+                       outputStream.write(buffer, rc2);
+               }
        }
 
        String output = outputStream.str();
@@ -183,8 +207,8 @@ ProcessResult Process::Run(void)
                exitcode = WEXITSTATUS(status);
        } else if (WIFSIGNALED(status)) {
                std::ostringstream outputbuf;
-               outputbuf << "Process was terminated by signal " << WTERMSIG(status);
-               output = outputbuf.str();
+               outputbuf << "<Terminated by signal " << WTERMSIG(status) << ".>";
+               output = output + outputbuf.str();
                exitcode = 128;
        } else {
                exitcode = 128;
index 009311b4721ec2319a21bbcd7ad6918891b6a829..e2f9904211bbbd0b5c727199ce07cd2b3fd7a96d 100644 (file)
@@ -26,7 +26,7 @@
 using namespace icinga;
 
 Process::Process(const std::vector<String>& arguments, const Dictionary::Ptr& extraEnvironment)
-       : m_Arguments(arguments), m_ExtraEnvironment(extraEnvironment)
+       : m_Arguments(arguments), m_ExtraEnvironment(extraEnvironment), m_Timeout(600)
 { }
 
 std::vector<String> Process::SplitCommand(const Value& command)
@@ -54,3 +54,13 @@ std::vector<String> Process::SplitCommand(const Value& command)
 #endif
        return args;
 }
+
+void Process::SetTimeout(double timeout)
+{
+       m_Timeout = timeout;
+}
+
+double Process::GetTimeout(void) const
+{
+       return m_Timeout;
+}
index 8b0ac1c23ff139ab5ff498e7de48743bfce854e6..1587752a6fdce8213728c83961b34808d6d568a5 100644 (file)
@@ -61,6 +61,9 @@ public:
 
        Process(const std::vector<String>& arguments, const Dictionary::Ptr& extraEnvironment = Dictionary::Ptr());
 
+       void SetTimeout(double timeout);
+       double GetTimeout(void) const;
+
        ProcessResult Run(void);
 
        static std::vector<String> SplitCommand(const Value& command);
@@ -68,6 +71,8 @@ private:
        std::vector<String> m_Arguments;
        Dictionary::Ptr m_ExtraEnvironment;
 
+       double m_Timeout;
+
 #ifndef _WIN32
        pid_t m_Pid;
 
index 1e0c3fb3b7dcb50a7f8553d6ac8ef47a8ee52870..32d674979928e0f9a011d01a4e919bcad51afecf 100644 (file)
@@ -316,7 +316,8 @@ type Command {
        },
        %attribute dictionary "macros" {
            %attribute string "*"
-       }
+       },
+       %attribute number "timeout"
 /*    } */
 }
 
index f1dc932f15a404c52fb53d210a68eb8afac6a673..987d39cd293674300c8becd21270ed2667723d51 100644 (file)
@@ -67,6 +67,11 @@ Dictionary::Ptr PluginCheckTask::ScriptFunc(const Service::Ptr& service)
 
        Process::Ptr process = boost::make_shared<Process>(Process::SplitCommand(command), envMacros);
 
+       Value timeout = commandObj->Get("timeout");
+
+       if (!timeout.IsEmpty())
+               process->SetTimeout(timeout);
+
        ProcessResult pr = process->Run();
 
        String output = pr.Output;
index 54cafcdf3c6e0008fb1114c0b1bb072dd9a2b062..bb71100625dc44fb73afe535a79813807b8bab72 100644 (file)
@@ -65,5 +65,10 @@ void PluginEventTask::ScriptFunc(const Service::Ptr& service)
 
        Process::Ptr process = boost::make_shared<Process>(Process::SplitCommand(command), envMacros);
 
+       Value timeout = commandObj->Get("timeout");
+
+       if (!timeout.IsEmpty())
+               process->SetTimeout(timeout);
+
        process->Run();
 }
index 7e4084270109290a402302af40b45ffd76f37b1b..63f893bd756e5e9e017ecd6d1404fea12d37b6cf 100644 (file)
@@ -78,6 +78,11 @@ void PluginNotificationTask::ScriptFunc(const Notification::Ptr& notification, c
 
        Process::Ptr process = boost::make_shared<Process>(Process::SplitCommand(command), envMacros);
 
+       Value timeout = commandObj->Get("timeout");
+
+       if (!timeout.IsEmpty())
+               process->SetTimeout(timeout);
+
        ProcessResult pr = process->Run();
 
        if (pr.ExitStatus != 0) {