summaryrefslogtreecommitdiffstats
path: root/src/Common
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common')
-rw-r--r--src/Common/Backends/SystemBackendPosix.cpp57
-rw-r--r--src/Common/Backends/SystemBackendPosix.h7
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);