Fix command timeout.

Fixes #6232
This commit is contained in:
Gunnar Beutner 2014-05-19 13:09:26 +02:00
parent 1f32630b42
commit b814d89ce0
2 changed files with 61 additions and 41 deletions

View File

@ -155,11 +155,12 @@ void Process::IOThreadProc(int tid)
pollfd *pfds = NULL; pollfd *pfds = NULL;
#endif /* _WIN32 */ #endif /* _WIN32 */
int count = 0; int count = 0;
double now;
Utility::SetThreadName("ProcessIO"); Utility::SetThreadName("ProcessIO");
for (;;) { for (;;) {
double now, timeout = -1; double timeout = -1;
now = Utility::GetTime(); now = Utility::GetTime();
@ -202,8 +203,10 @@ void Process::IOThreadProc(int tid)
} }
} }
if (timeout != -1) if (timeout < 0.01)
timeout *= 1000; timeout = 0.5;
timeout *= 1000;
#ifdef _WIN32 #ifdef _WIN32
DWORD rc = WaitForMultipleObjects(count, handles, FALSE, timeout == -1 ? INFINITE : static_cast<DWORD>(timeout)); DWORD rc = WaitForMultipleObjects(count, handles, FALSE, timeout == -1 ? INFINITE : static_cast<DWORD>(timeout));
@ -214,6 +217,8 @@ void Process::IOThreadProc(int tid)
continue; continue;
#endif /* _WIN32 */ #endif /* _WIN32 */
now = Utility::GetTime();
{ {
boost::mutex::scoped_lock lock(l_ProcessMutex[tid]); boost::mutex::scoped_lock lock(l_ProcessMutex[tid]);
@ -228,27 +233,36 @@ void Process::IOThreadProc(int tid)
#endif /* _WIN32 */ #endif /* _WIN32 */
for (int i = 1; i < count; i++) { for (int i = 1; i < count; i++) {
#ifdef _WIN32 std::map<ConsoleHandle, ProcessHandle>::iterator it2;
if (rc == WAIT_OBJECT_0 + i) { it2 = l_FDs[tid].find(pfds[i].fd);
#else /* _WIN32 */
if (pfds[i].revents & (POLLIN | POLLHUP | POLLERR)) {
std::map<ConsoleHandle, ProcessHandle>::iterator it2;
it2 = l_FDs[tid].find(pfds[i].fd);
if (it2 == l_FDs[tid].end()) if (it2 == l_FDs[tid].end())
continue; /* This should never happen. */ continue; /* This should never happen. */
#endif /* _WIN32 */ std::map<ProcessHandle, Process::Ptr>::iterator it;
std::map<ProcessHandle, Process::Ptr>::iterator it;
#ifdef _WIN32 #ifdef _WIN32
it = l_Processes[tid].find(handles[i]); it = l_Processes[tid].find(handles[i]);
#else /* _WIN32 */ #else /* _WIN32 */
it = l_Processes[tid].find(it2->second); it = l_Processes[tid].find(it2->second);
#endif /* _WIN32 */ #endif /* _WIN32 */
if (it == l_Processes[tid].end()) if (it == l_Processes[tid].end())
continue; /* This should never happen. */ 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()) { if (!it->second->DoEvents()) {
#ifdef _WIN32 #ifdef _WIN32
CloseHandle(it->first); CloseHandle(it->first);
@ -562,42 +576,48 @@ void Process::Run(const boost::function<void(const ProcessResult&)>& callback)
bool Process::DoEvents(void) bool Process::DoEvents(void)
{ {
if (m_Timeout != 0) { bool is_timeout = false;
double timeout = m_Timeout - (Utility::GetTime() - m_Result.ExecutionStart);
if (timeout < 0) { if (m_Timeout != 0) {
double timeout = m_Result.ExecutionStart + m_Timeout;
if (timeout < Utility::GetTime()) {
m_OutputStream << "<Timeout exceeded.>"; m_OutputStream << "<Timeout exceeded.>";
#ifdef _WIN32 #ifdef _WIN32
TerminateProcess(m_Process, 1); TerminateProcess(m_Process, 1);
#else /* _WIN32 */ #else /* _WIN32 */
kill(m_Process, SIGKILL); kill(m_Process, SIGKILL);
#endif /* _WIN32 */ #endif /* _WIN32 */
is_timeout = true;
} }
} }
char buffer[512]; if (!is_timeout) {
for (;;) { char buffer[512];
for (;;) {
#ifdef _WIN32 #ifdef _WIN32
DWORD rc; DWORD rc;
if (!ReadFile(m_FD, buffer, sizeof(buffer), &rc, NULL) || rc == 0) 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; 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(); String output = m_OutputStream.str();

View File

@ -8,7 +8,7 @@ abstract class Command : DynamicObject
[config] Value command (CommandLine); [config] Value command (CommandLine);
[config] Value arguments; [config] Value arguments;
[config] Value timeout { [config] Value timeout {
default {{{ return 300; }}} default {{{ return 60; }}}
}; };
[config] Dictionary::Ptr env; [config] Dictionary::Ptr env;
}; };