diff options
Diffstat (limited to 'src/Common/Backends')
-rw-r--r-- | src/Common/Backends/SystemBackendPosix.cpp | 57 | ||||
-rw-r--r-- | src/Common/Backends/SystemBackendPosix.h | 7 |
2 files changed, 53 insertions, 11 deletions
diff --git a/src/Common/Backends/SystemBackendPosix.cpp b/src/Common/Backends/SystemBackendPosix.cpp index 267e82e..62067c2 100644 --- a/src/Common/Backends/SystemBackendPosix.cpp +++ b/src/Common/Backends/SystemBackendPosix.cpp @@ -18,6 +18,7 @@ */ #include "SystemBackendPosix.h" +#include <Net/FdManager.h> #include <cstdio> #include <cstdlib> @@ -39,7 +40,9 @@ namespace Backends { SystemBackendPosix SystemBackendPosix::backend; std::map<pid_t, sigc::slot<void, int> > SystemBackendPosix::processes; -std::map<pid_t, std::pair<sigc::slot<void, int, const std::string&>, int> > SystemBackendPosix::processesWithOutput; +std::map<pid_t, sigc::slot<void, int, const std::string&> > SystemBackendPosix::processesWithOutput; +std::map<pid_t, int> SystemBackendPosix::processesWOHandles; +std::map<pid_t, std::string > SystemBackendPosix::processesWOOutput; void SystemBackendPosix::setChildHandler() { @@ -117,20 +120,24 @@ void SystemBackendPosix::childHandler(int) { processes.erase(it); } else { - std::map<pid_t, std::pair<sigc::slot<void, int, const std::string&>, int> >::iterator it2 = processesWithOutput.find(pid); + std::map<pid_t, sigc::slot<void, int, const std::string&> >::iterator it2 = processesWithOutput.find(pid); if(it2 != processesWithOutput.end()) { char buffer[1024]; ssize_t n; - std::string output; + std::string &output = processesWOOutput[pid]; + int handle = processesWOHandles[pid]; - while((n = read(it2->second.second, buffer, sizeof(buffer))) > 0) + while((n = read(handle, buffer, sizeof(buffer))) > 0) output += std::string(buffer, n); - close(it2->second.second); + Net::FdManager::getFdManager()->unregisterFd(handle); + close(handle); - it2->second.first(status, output); + it2->second(status, output); processesWithOutput.erase(it2); + processesWOHandles.erase(pid); + processesWOOutput.erase(pid); } } } @@ -138,6 +145,28 @@ void SystemBackendPosix::childHandler(int) { setChildHandler(); } +void SystemBackendPosix::outputHandler(short events, pid_t pid) { + char buf[1024]; + + if(events & POLLIN) { + sigset_t set, oldset; + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + sigprocmask(SIG_BLOCK, &set, &oldset); + + ssize_t ret; + + std::map<pid_t, int>::iterator handle = processesWOHandles.find(pid); + if(handle == processesWOHandles.end()) + return; + + while((ret = read(handle->second, buf, sizeof(buf))) > 0) + processesWOOutput[pid] += std::string(buf, ret); + + sigprocmask(SIG_SETMASK, &oldset, 0); + } +} + std::pair<char**, char**> SystemBackendPosix::makeArgs(const std::string &filename, const std::vector<std::string> &argv, const std::vector<std::string> &env) { char **argvp, **envp; @@ -215,10 +244,13 @@ bool SystemBackendPosix::execWithOutput(const sigc::slot<void, int, const std::s int saveStdout = dup(STDOUT_FILENO); int pipeHandles[2]; - pipe(pipeHandles); // TODO Better pipe handling + pipe(pipeHandles); fcntl(pipeHandles[0], F_SETFD, FD_CLOEXEC); + int flags = fcntl(pipeHandles[0], F_GETFL, 0); + fcntl(pipeHandles[0], F_SETFL, flags | O_NONBLOCK); + sigset_t set, oldset; sigemptyset(&set); sigaddset(&set, SIGCHLD); @@ -227,10 +259,15 @@ bool SystemBackendPosix::execWithOutput(const sigc::slot<void, int, const std::s dup2(pipeHandles[1], STDOUT_FILENO); // set the new pipe as stdout close(pipeHandles[1]); - bool ret (posix_spawnp(&pid, filename.c_str(), 0, 0, args.first, args.second) == 0); + bool ret = (posix_spawnp(&pid, filename.c_str(), 0, 0, args.first, args.second) == 0); + + if(ret) { + processesWithOutput.insert(std::make_pair(pid, resultHandler)); + processesWOHandles.insert(std::make_pair(pid, pipeHandles[0])); + processesWOOutput.insert(std::make_pair(pid, std::string())); - if(ret) - processesWithOutput.insert(std::make_pair(pid, std::make_pair(resultHandler, pipeHandles[0]))); + Net::FdManager::getFdManager()->registerFd(pipeHandles[0], sigc::bind(sigc::ptr_fun(&SystemBackendPosix::outputHandler), pid), POLLIN); + } dup2(saveStdout, STDOUT_FILENO); // restore old stdout close(saveStdout); diff --git a/src/Common/Backends/SystemBackendPosix.h b/src/Common/Backends/SystemBackendPosix.h index b7f364a..59dd2d8 100644 --- a/src/Common/Backends/SystemBackendPosix.h +++ b/src/Common/Backends/SystemBackendPosix.h @@ -38,12 +38,17 @@ class SystemBackendPosix : public SystemBackend { private: static SystemBackendPosix backend; static std::map<pid_t, sigc::slot<void, int> > processes; - static std::map<pid_t, std::pair<sigc::slot<void, int, const std::string&>, int> > processesWithOutput; + + static std::map<pid_t, sigc::slot<void, int, const std::string&> > processesWithOutput; + static std::map<pid_t, int> processesWOHandles; + static std::map<pid_t, std::string > processesWOOutput; static void setChildHandler(); static void childHandler(int); + static void outputHandler(short events, pid_t pid); + static std::pair<char**, char**> makeArgs(const std::string &filename, const std::vector<std::string> &argv, const std::vector<std::string> &env); static void destroyArgs(std::pair<char**, char**> args); |