From b814d89ce0334548795f5681ddf1a43e67de9698 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Mon, 19 May 2014 13:09:26 +0200 Subject: [PATCH] Fix command timeout. Fixes #6232 --- lib/base/process.cpp | 100 +++++++++++++++++++++++++----------------- lib/icinga/command.ti | 2 +- 2 files changed, 61 insertions(+), 41 deletions(-) diff --git a/lib/base/process.cpp b/lib/base/process.cpp index d6366324d..c4d5eb5f0 100644 --- a/lib/base/process.cpp +++ b/lib/base/process.cpp @@ -155,11 +155,12 @@ void Process::IOThreadProc(int tid) pollfd *pfds = NULL; #endif /* _WIN32 */ int count = 0; + double now; Utility::SetThreadName("ProcessIO"); for (;;) { - double now, timeout = -1; + double timeout = -1; now = Utility::GetTime(); @@ -202,8 +203,10 @@ void Process::IOThreadProc(int tid) } } - if (timeout != -1) - timeout *= 1000; + if (timeout < 0.01) + timeout = 0.5; + + timeout *= 1000; #ifdef _WIN32 DWORD rc = WaitForMultipleObjects(count, handles, FALSE, timeout == -1 ? INFINITE : static_cast(timeout)); @@ -214,6 +217,8 @@ void Process::IOThreadProc(int tid) continue; #endif /* _WIN32 */ + now = Utility::GetTime(); + { boost::mutex::scoped_lock lock(l_ProcessMutex[tid]); @@ -228,27 +233,36 @@ void Process::IOThreadProc(int tid) #endif /* _WIN32 */ for (int i = 1; i < count; i++) { -#ifdef _WIN32 - if (rc == WAIT_OBJECT_0 + i) { -#else /* _WIN32 */ - if (pfds[i].revents & (POLLIN | POLLHUP | POLLERR)) { - std::map::iterator it2; - it2 = l_FDs[tid].find(pfds[i].fd); + std::map::iterator it2; + it2 = l_FDs[tid].find(pfds[i].fd); - if (it2 == l_FDs[tid].end()) - continue; /* This should never happen. */ + if (it2 == l_FDs[tid].end()) + continue; /* This should never happen. */ -#endif /* _WIN32 */ - std::map::iterator it; + std::map::iterator it; #ifdef _WIN32 - it = l_Processes[tid].find(handles[i]); + it = l_Processes[tid].find(handles[i]); #else /* _WIN32 */ - it = l_Processes[tid].find(it2->second); + it = l_Processes[tid].find(it2->second); #endif /* _WIN32 */ - if (it == l_Processes[tid].end()) - continue; /* This should never happen. */ + if (it == l_Processes[tid].end()) + continue; /* This should never happen. */ + bool is_timeout = false; + + if (it->second->m_Timeout != 0) { + double timeout = it->second->m_Result.ExecutionStart + it->second->m_Timeout; + + if (timeout < now) + is_timeout = true; + } + +#ifdef _WIN32 + if (rc == WAIT_OBJECT_0 + i || is_timeout) { +#else /* _WIN32 */ + if (pfds[i].revents & (POLLIN | POLLHUP | POLLERR) || is_timeout) { +#endif /* _WIN32 */ if (!it->second->DoEvents()) { #ifdef _WIN32 CloseHandle(it->first); @@ -562,42 +576,48 @@ void Process::Run(const boost::function& callback) bool Process::DoEvents(void) { - if (m_Timeout != 0) { - double timeout = m_Timeout - (Utility::GetTime() - m_Result.ExecutionStart); + bool is_timeout = false; - if (timeout < 0) { + if (m_Timeout != 0) { + double timeout = m_Result.ExecutionStart + m_Timeout; + + if (timeout < Utility::GetTime()) { m_OutputStream << ""; #ifdef _WIN32 TerminateProcess(m_Process, 1); #else /* _WIN32 */ kill(m_Process, SIGKILL); #endif /* _WIN32 */ + + is_timeout = true; } } - char buffer[512]; - for (;;) { + if (!is_timeout) { + char buffer[512]; + for (;;) { #ifdef _WIN32 - DWORD rc; - if (!ReadFile(m_FD, buffer, sizeof(buffer), &rc, NULL) || rc == 0) + DWORD rc; + if (!ReadFile(m_FD, buffer, sizeof(buffer), &rc, NULL) || rc == 0) + break; +#else /* _WIN32 */ + int rc = read(m_FD, buffer, sizeof(buffer)); + + if (rc < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) + return true; + + if (rc > 0) { +#endif /* _WIN32 */ + m_OutputStream.write(buffer, rc); +#ifdef _WIN32 + return true; +#else /* _WIN32 */ + continue; + } +#endif /* _WIN32 */ + break; -#else /* _WIN32 */ - int rc = read(m_FD, buffer, sizeof(buffer)); - - if (rc < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) - return true; - - if (rc > 0) { -#endif /* _WIN32 */ - m_OutputStream.write(buffer, rc); -#ifdef _WIN32 - return true; -#else /* _WIN32 */ - continue; } -#endif /* _WIN32 */ - - break; } String output = m_OutputStream.str(); diff --git a/lib/icinga/command.ti b/lib/icinga/command.ti index 895533d86..ca6e86244 100644 --- a/lib/icinga/command.ti +++ b/lib/icinga/command.ti @@ -8,7 +8,7 @@ abstract class Command : DynamicObject [config] Value command (CommandLine); [config] Value arguments; [config] Value timeout { - default {{{ return 300; }}} + default {{{ return 60; }}} }; [config] Dictionary::Ptr env; };