From 963125f746a75d013d5f11102c7a47b4188f7f5f Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 5 Aug 2014 18:01:01 +0200 Subject: [PATCH] ExternalCommandListener: Use threads per client connection fixes #6589 --- components/compat/externalcommandlistener.cpp | 93 +++++++++++-------- components/compat/externalcommandlistener.hpp | 1 + 2 files changed, 54 insertions(+), 40 deletions(-) diff --git a/components/compat/externalcommandlistener.cpp b/components/compat/externalcommandlistener.cpp index 437cf6943..a89d32803 100644 --- a/components/compat/externalcommandlistener.cpp +++ b/components/compat/externalcommandlistener.cpp @@ -99,50 +99,63 @@ void ExternalCommandListener::CommandPipeThread(const String& commandPath) for (;;) { int fd; - do { - fd = open(commandPath.CStr(), O_RDONLY); - } while (fd < 0 && errno == EINTR); + try { + do { + fd = open(commandPath.CStr(), O_RDONLY); + } while (fd < 0 && errno == EINTR); - if (fd < 0) { - std::ostringstream msgbuf; - msgbuf << "open() for fifo path '" << commandPath << "'failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\""; - Log(LogCritical, "ExternalCommandListener", msgbuf.str()); - return; - } - - FILE *fp = fdopen(fd, "r"); - - if (fp == NULL) { - std::ostringstream msgbuf; - msgbuf << "fdopen() for fifo path '" << commandPath << "'failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\""; - Log(LogCritical, "ExternalCommandListener", msgbuf.str()); - return; - } - - const int linesize = 128 * 1024; - char *line = new char[linesize]; - - while (fgets(line, linesize, fp) != NULL) { - // remove trailing new-line - while (strlen(line) > 0 && - (line[strlen(line) - 1] == '\r' || line[strlen(line) - 1] == '\n')) - line[strlen(line) - 1] = '\0'; - - String command = line; - - try { - Log(LogInformation, "ExternalCommandListener", "Executing external command: " + command); - - ExternalCommandProcessor::Execute(command); - } catch (const std::exception&) { + if (fd < 0) { std::ostringstream msgbuf; - msgbuf << "External command failed."; - Log(LogWarning, "ExternalCommandListener", msgbuf.str()); + msgbuf << "open() for fifo path '" << commandPath << "'failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\""; + Log(LogCritical, "ExternalCommandListener", msgbuf.str()); + return; } - } - delete line; - fclose(fp); + + + Log(LogNotice, "ExternalCommandListener", "Client connected"); + Utility::QueueAsyncCallback(boost::bind(&ExternalCommandListener::ClientHandler, this, commandPath, fd)); + } catch (std::exception&) { + Log(LogCritical, "ExternalCommandListener", "Cannot accept new connection."); + } } } + +void ExternalCommandListener::ClientHandler(const String& commandPath, int fd) +{ + FILE *fp = fdopen(fd, "r"); + + if (fp == NULL) { + std::ostringstream msgbuf; + msgbuf << "fdopen() for fifo path '" << commandPath << "'failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\""; + Log(LogCritical, "ExternalCommandListener", msgbuf.str()); + return; + } + + const int linesize = 128 * 1024; + char *line = new char[linesize]; + + while (fgets(line, linesize, fp) != NULL) { + // remove trailing new-line + while (strlen(line) > 0 && + (line[strlen(line) - 1] == '\r' || line[strlen(line) - 1] == '\n')) + line[strlen(line) - 1] = '\0'; + } + + String command = line; + + try { + Log(LogInformation, "ExternalCommandListener", "Executing external command: " + command); + + ExternalCommandProcessor::Execute(command); + } catch (const std::exception&) { + std::ostringstream msgbuf; + msgbuf << "External command failed."; + Log(LogWarning, "ExternalCommandListener", msgbuf.str()); + return; + } + + delete line; + fclose(fp); +} #endif /* _WIN32 */ diff --git a/components/compat/externalcommandlistener.hpp b/components/compat/externalcommandlistener.hpp index 665b0272a..db65fadb2 100644 --- a/components/compat/externalcommandlistener.hpp +++ b/components/compat/externalcommandlistener.hpp @@ -49,6 +49,7 @@ private: boost::thread m_CommandThread; void CommandPipeThread(const String& commandPath); + void ClientHandler(const String& commandPath, int fd); #endif /* _WIN32 */ };