Implement command timeouts.

Fixes #2723
This commit is contained in:
Gunnar Beutner 2013-06-13 12:05:24 +02:00
parent d042a181bd
commit e30d3c5691
7 changed files with 63 additions and 8 deletions

View 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;
if (rc <= 0)
break;
timeout = 0;
outputStream.write(buffer, rc);
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 (rc1 > 0) {
int rc2 = read(fd, buffer, sizeof(buffer));
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;

View 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;
}

View 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;

View File

@ -316,7 +316,8 @@ type Command {
},
%attribute dictionary "macros" {
%attribute string "*"
}
},
%attribute number "timeout"
/* } */
}

View 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;

View 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();
}

View 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) {