Removed unused code from procs library, updated and simplified connector handler in controller.

This commit is contained in:
Thulinma 2015-04-16 12:23:03 +02:00
parent 184f7ad6c8
commit 243a05c8af
4 changed files with 56 additions and 439 deletions

View file

@ -21,8 +21,7 @@
#include <stdio.h> #include <stdio.h>
#include "timing.h" #include "timing.h"
std::map<pid_t, std::string> Util::Procs::plist; std::set<pid_t> Util::Procs::plist;
std::map<pid_t, Util::TerminationNotifier> Util::Procs::exitHandlers;
bool Util::Procs::handler_set = false; bool Util::Procs::handler_set = false;
@ -39,7 +38,7 @@ static bool childRunning(pid_t p) {
} }
/// sends sig 0 to process (pid). returns true if process is running /// sends sig 0 to process (pid). returns true if process is running
bool Util::Procs::isRunnning(pid_t pid){ bool Util::Procs::isRunning(pid_t pid){
return !kill(pid, 0); return !kill(pid, 0);
} }
@ -49,8 +48,8 @@ bool Util::Procs::isRunnning(pid_t pid){
/// all remaining children. Waits one more second for cleanup to finish, then exits. /// all remaining children. Waits one more second for cleanup to finish, then exits.
void Util::Procs::exit_handler() { void Util::Procs::exit_handler() {
int waiting = 0; int waiting = 0;
std::map<pid_t, std::string> listcopy = plist; std::set<pid_t> listcopy = plist;
std::map<pid_t, std::string>::iterator it; std::set<pid_t>::iterator it;
if (listcopy.empty()) { if (listcopy.empty()) {
return; return;
} }
@ -58,7 +57,7 @@ void Util::Procs::exit_handler() {
//wait up to 0.5 second for applications to shut down //wait up to 0.5 second for applications to shut down
while (!listcopy.empty() && waiting <= 25) { while (!listcopy.empty() && waiting <= 25) {
for (it = listcopy.begin(); it != listcopy.end(); it++) { for (it = listcopy.begin(); it != listcopy.end(); it++) {
if (!childRunning((*it).first)) { if (!childRunning(*it)) {
listcopy.erase(it); listcopy.erase(it);
break; break;
} }
@ -76,8 +75,8 @@ void Util::Procs::exit_handler() {
//send sigint to all remaining //send sigint to all remaining
if (!listcopy.empty()) { if (!listcopy.empty()) {
for (it = listcopy.begin(); it != listcopy.end(); it++) { for (it = listcopy.begin(); it != listcopy.end(); it++) {
DEBUG_MSG(DLVL_DEVEL, "SIGINT %d: %s", (*it).first, (*it).second.c_str()); DEBUG_MSG(DLVL_DEVEL, "SIGINT %d", *it);
kill((*it).first, SIGINT); kill(*it, SIGINT);
} }
} }
@ -86,7 +85,7 @@ void Util::Procs::exit_handler() {
//wait up to 5 seconds for applications to shut down //wait up to 5 seconds for applications to shut down
while (!listcopy.empty() && waiting <= 250) { while (!listcopy.empty() && waiting <= 250) {
for (it = listcopy.begin(); it != listcopy.end(); it++) { for (it = listcopy.begin(); it != listcopy.end(); it++) {
if (!childRunning((*it).first)) { if (!childRunning(*it)) {
listcopy.erase(it); listcopy.erase(it);
break; break;
} }
@ -104,8 +103,8 @@ void Util::Procs::exit_handler() {
//send sigkill to all remaining //send sigkill to all remaining
if (!listcopy.empty()) { if (!listcopy.empty()) {
for (it = listcopy.begin(); it != listcopy.end(); it++) { for (it = listcopy.begin(); it != listcopy.end(); it++) {
DEBUG_MSG(DLVL_DEVEL, "SIGKILL %d: %s", (*it).first, (*it).second.c_str()); DEBUG_MSG(DLVL_DEVEL, "SIGKILL %d", *it);
kill((*it).first, SIGKILL); kill(*it, SIGKILL);
} }
} }
@ -114,7 +113,7 @@ void Util::Procs::exit_handler() {
//wait up to 1 second for applications to shut down //wait up to 1 second for applications to shut down
while (!listcopy.empty() && waiting <= 50) { while (!listcopy.empty() && waiting <= 50) {
for (it = listcopy.begin(); it != listcopy.end(); it++) { for (it = listcopy.begin(); it != listcopy.end(); it++) {
if (!childRunning((*it).first)) { if (!childRunning(*it)) {
listcopy.erase(it); listcopy.erase(it);
break; break;
} }
@ -170,23 +169,15 @@ void Util::Procs::childsig_handler(int signum) {
return; return;
} }
#if DEBUG >= DLVL_HIGH
std::string pname = plist[ret];
#endif
plist.erase(ret); plist.erase(ret);
#if DEBUG >= DLVL_HIGH #if DEBUG >= DLVL_HIGH
if (!isActive(pname)) { if (!isActive(pname)) {
DEBUG_MSG(DLVL_HIGH, "Process %s fully terminated", pname.c_str()); DEBUG_MSG(DLVL_HIGH, "Process %d fully terminated", ret);
} else { } else {
DEBUG_MSG(DLVL_HIGH, "Child process %d exited", ret); DEBUG_MSG(DLVL_HIGH, "Child process %d exited", ret);
} }
#endif #endif
if (exitHandlers.count(ret) > 0) {
TerminationNotifier tn = exitHandlers[ret];
exitHandlers.erase(ret);
tn(ret, exitcode);
}
} }
} }
@ -195,8 +186,8 @@ void Util::Procs::childsig_handler(int signum) {
std::string Util::Procs::getOutputOf(char * const * argv) { std::string Util::Procs::getOutputOf(char * const * argv) {
std::string ret; std::string ret;
int fin = 0, fout = -1, ferr = 0; int fin = 0, fout = -1, ferr = 0;
StartPiped("output_getter", argv, &fin, &fout, &ferr); pid_t myProc = StartPiped(argv, &fin, &fout, &ferr);
while (isActive("output_getter")) { while (isActive(myProc)) {
Util::sleep(100); Util::sleep(100);
} }
FILE * outFile = fdopen(fout, "r"); FILE * outFile = fdopen(fout, "r");
@ -210,258 +201,12 @@ std::string Util::Procs::getOutputOf(char * const * argv) {
return ret; return ret;
} }
/// Runs the given command and returns the stdout output as a string.
std::string Util::Procs::getOutputOf(std::string cmd) {
std::string ret;
int fin = 0, fout = -1, ferr = 0;
StartPiped("output_getter", cmd, &fin, &fout, &ferr);
while (isActive("output_getter")) {
Util::sleep(100);
}
FILE * outFile = fdopen(fout, "r");
char * fileBuf = 0;
size_t fileBufLen = 0;
while (!(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)) {
ret += fileBuf;
}
free(fileBuf);
fclose(outFile);
return ret;
}
/// Attempts to run the command cmd.
/// Replaces the current process - use after forking first!
/// This function will never return - it will either run the given
/// command or kill itself with return code 42.
void Util::Procs::runCmd(std::string & cmd) {
//split cmd into arguments
//supports a maximum of 20 arguments
char * tmp = (char *)cmd.c_str();
char * tmp2 = 0;
char * args[21];
int i = 0;
tmp2 = strtok(tmp, " ");
args[0] = tmp2;
while (tmp2 != 0 && (i < 20)) {
tmp2 = strtok(0, " ");
++i;
args[i] = tmp2;
}
if (i == 20) {
args[20] = 0;
}
//execute the command
execvp(args[0], args);
DEBUG_MSG(DLVL_ERROR, "Error running %s: %s", cmd.c_str(), strerror(errno));
_exit(42);
}
/// Starts a new process if the name is not already active.
/// \return 0 if process was not started, process PID otherwise.
/// \arg name Name for this process - only used internally.
/// \arg cmd Commandline for this process.
pid_t Util::Procs::Start(std::string name, std::string cmd) {
if (isActive(name)) {
return getPid(name);
}
setHandler();
pid_t ret = fork();
if (ret == 0) {
runCmd(cmd);
} else {
if (ret > 0) {
DEBUG_MSG(DLVL_HIGH, "Process %s started, PID %d: %s", name.c_str(), ret, cmd.c_str());
plist.insert(std::pair<pid_t, std::string>(ret, name));
} else {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started: fork() failed", name.c_str());
return 0;
}
}
return ret;
}
/// Starts two piped processes if the name is not already active.
/// \return 0 if process was not started, sub (sending) process PID otherwise.
/// \arg name Name for this process - only used internally.
/// \arg cmd Commandline for sub (sending) process.
/// \arg cmd2 Commandline for main (receiving) process.
pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2) {
if (isActive(name)) {
return getPid(name);
}
setHandler();
int pfildes[2];
if (pipe(pfildes) == -1) {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. Pipe creation failed.", name.c_str());
return 0;
}
int devnull = open("/dev/null", O_RDWR);
pid_t ret = fork();
if (ret == 0) {
close(pfildes[0]);
dup2(pfildes[1], STDOUT_FILENO);
close(pfildes[1]);
dup2(devnull, STDIN_FILENO);
dup2(devnull, STDERR_FILENO);
runCmd(cmd);
} else {
if (ret > 0) {
plist.insert(std::pair<pid_t, std::string>(ret, name));
} else {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
close(pfildes[1]);
close(pfildes[0]);
return 0;
}
}
pid_t ret2 = fork();
if (ret2 == 0) {
close(pfildes[1]);
dup2(pfildes[0], STDIN_FILENO);
close(pfildes[0]);
dup2(devnull, STDOUT_FILENO);
dup2(devnull, STDERR_FILENO);
runCmd(cmd2);
} else {
if (ret2 > 0) {
DEBUG_MSG(DLVL_HIGH, "Process %s started, PIDs (%d, %d): %s | %s", name.c_str(), ret, ret2, cmd.c_str(), cmd2.c_str());
plist.insert(std::pair<pid_t, std::string>(ret2, name));
} else {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
Stop(name);
close(pfildes[1]);
close(pfildes[0]);
return 0;
}
}
close(pfildes[1]);
close(pfildes[0]);
return ret;
}
/// Starts three piped processes if the name is not already active.
/// \return 0 if process was not started, sub (sending) process PID otherwise.
/// \arg name Name for this process - only used internally.
/// \arg cmd Commandline for sub (sending) process.
/// \arg cmd2 Commandline for sub (middle) process.
/// \arg cmd3 Commandline for main (receiving) process.
pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, std::string cmd3) {
if (isActive(name)) {
return getPid(name);
}
setHandler();
int pfildes[2];
int pfildes2[2];
if (pipe(pfildes) == -1) {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. Pipe creation failed.", name.c_str());
return 0;
}
if (pipe(pfildes2) == -1) {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. Pipe creation failed.", name.c_str());
return 0;
}
int devnull = open("/dev/null", O_RDWR);
pid_t ret = fork();
if (ret == 0) {
close(pfildes[0]);
dup2(pfildes[1], STDOUT_FILENO);
close(pfildes[1]);
dup2(devnull, STDIN_FILENO);
dup2(devnull, STDERR_FILENO);
close(pfildes2[1]);
close(pfildes2[0]);
runCmd(cmd);
} else {
if (ret > 0) {
plist.insert(std::pair<pid_t, std::string>(ret, name));
} else {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
close(pfildes[1]);
close(pfildes[0]);
close(pfildes2[1]);
close(pfildes2[0]);
return 0;
}
}
pid_t ret2 = fork();
if (ret2 == 0) {
close(pfildes[1]);
close(pfildes2[0]);
dup2(pfildes[0], STDIN_FILENO);
close(pfildes[0]);
dup2(pfildes2[1], STDOUT_FILENO);
close(pfildes2[1]);
dup2(devnull, STDERR_FILENO);
runCmd(cmd2);
} else {
if (ret2 > 0) {
DEBUG_MSG(DLVL_HIGH, "Process %s started, PIDs (%d, %d): %s | %s", name.c_str(), ret, ret2, cmd.c_str(), cmd2.c_str());
plist.insert(std::pair<pid_t, std::string>(ret2, name));
} else {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
Stop(name);
close(pfildes[1]);
close(pfildes[0]);
close(pfildes2[1]);
close(pfildes2[0]);
return 0;
}
}
close(pfildes[1]);
close(pfildes[0]);
pid_t ret3 = fork();
if (ret3 == 0) {
close(pfildes[1]);
close(pfildes[0]);
close(pfildes2[1]);
dup2(pfildes2[0], STDIN_FILENO);
close(pfildes2[0]);
dup2(devnull, STDOUT_FILENO);
dup2(devnull, STDERR_FILENO);
runCmd(cmd3);
} else {
if (ret3 > 0) {
DEBUG_MSG(DLVL_HIGH, "Process %s started, PIDs (%d, %d, %d): %s | %s | %s", name.c_str(), ret, ret2, ret3, cmd.c_str(), cmd2.c_str(), cmd3.c_str());
plist.insert(std::pair<pid_t, std::string>(ret3, name));
} else {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
Stop(name);
close(pfildes[1]);
close(pfildes[0]);
close(pfildes2[1]);
close(pfildes2[0]);
return 0;
}
}
return ret3;
}
/// Starts a new process with given fds if the name is not already active. /// Starts a new process with given fds if the name is not already active.
/// \return 0 if process was not started, process PID otherwise. /// \return 0 if process was not started, process PID otherwise.
/// \arg name Name for this process - only used internally.
/// \arg argv Command for this process. /// \arg argv Command for this process.
/// \arg fdin Standard input file descriptor. If null, /dev/null is assumed. Otherwise, if arg contains -1, a new fd is automatically allocated and written into this arg. Then the arg will be used as fd. /// \arg fdin Standard input file descriptor. If null, /dev/null is assumed. Otherwise, if arg contains -1, a new fd is automatically allocated and written into this arg. Then the arg will be used as fd.
/// \arg fdout Same as fdin, but for stdout. /// \arg fdout Same as fdin, but for stdout.
/// \arg fdout Same as fdin, but for stderr. /// \arg fdout Same as fdin, but for stderr.
pid_t Util::Procs::StartPiped(std::string name, char * const * argv, int * fdin, int * fdout, int * fderr) {
if (isActive(name)) {
DEBUG_MSG(DLVL_WARN, "Process %s already active - skipping start", name.c_str());
return getPid(name);
}
int pidtemp = StartPiped(argv, fdin, fdout, fderr);
if (pidtemp > 0) {
plist.insert(std::pair<pid_t, std::string>(pidtemp, name));
}
return pidtemp;
}
pid_t Util::Procs::StartPiped(char * const * argv, int * fdin, int * fdout, int * fderr) { pid_t Util::Procs::StartPiped(char * const * argv, int * fdin, int * fdout, int * fderr) {
pid_t pid; pid_t pid;
int pipein[2], pipeout[2], pipeerr[2]; int pipein[2], pipeout[2], pipeerr[2];
@ -574,6 +319,7 @@ pid_t Util::Procs::StartPiped(char * const * argv, int * fdin, int * fdout, int
} }
return 0; return 0;
} else { //parent } else { //parent
plist.insert(pid);
DEBUG_MSG(DLVL_HIGH, "Piped process %s started, PID %d", argv[0], pid); DEBUG_MSG(DLVL_HIGH, "Piped process %s started, PID %d", argv[0], pid);
if (devnull != -1) { if (devnull != -1) {
close(devnull); close(devnull);
@ -594,70 +340,6 @@ pid_t Util::Procs::StartPiped(char * const * argv, int * fdin, int * fdout, int
return pid; return pid;
} }
/// Starts a new process with given fds if the name is not already active.
/// \return 0 if process was not started, process PID otherwise.
/// \arg name Name for this process - only used internally.
/// \arg cmd Command for this process.
/// \arg fdin Standard input file descriptor. If null, /dev/null is assumed. Otherwise, if arg contains -1, a new fd is automatically allocated and written into this arg. Then the arg will be used as fd.
/// \arg fdout Same as fdin, but for stdout.
/// \arg fdout Same as fdin, but for stderr.
pid_t Util::Procs::StartPiped(std::string name, std::string cmd, int * fdin, int * fdout, int * fderr) {
//Convert the given command to a char * []
char * tmp = (char *)cmd.c_str();
char * tmp2 = 0;
char * args[21];
int i = 0;
tmp2 = strtok(tmp, " ");
args[0] = tmp2;
while (tmp2 != 0 && (i < 20)) {
tmp2 = strtok(0, " ");
++i;
args[i] = tmp2;
}
if (i == 20) {
args[20] = 0;
}
return StartPiped(name, args, fdin, fdout, fderr);
}
pid_t Util::Procs::StartPiped2(std::string name, std::string cmd1, std::string cmd2, int * fdin, int * fdout, int * fderr1, int * fderr2) {
int pfildes[2];
if (pipe(pfildes) == -1) {
DEBUG_MSG(DLVL_ERROR, "Pipe creation failed for process %s", name.c_str());
return 0;
}
pid_t res1 = StartPiped(name, cmd1, fdin, &pfildes[1], fderr1);
if (!res1) {
close(pfildes[1]);
close(pfildes[0]);
return 0;
}
pid_t res2 = StartPiped(name + "receiving", cmd2, &pfildes[0], fdout, fderr2);
if (!res2) {
Stop(res1);
close(pfildes[1]);
close(pfildes[0]);
return 0;
}
//we can close these because the fork in StartPiped() copies them.
close(pfildes[1]);
close(pfildes[0]);
return res1;
}
/// Stops the named process, if running.
/// \arg name (Internal) name of process to stop
void Util::Procs::Stop(std::string name) {
int max = 5;
while (isActive(name)) {
Stop(getPid(name));
max--;
if (max <= 0) {
return;
}
}
}
/// Stops the process with this pid, if running. /// Stops the process with this pid, if running.
/// \arg name The PID of the process to stop. /// \arg name The PID of the process to stop.
void Util::Procs::Stop(pid_t name) { void Util::Procs::Stop(pid_t name) {
@ -672,10 +354,10 @@ void Util::Procs::Murder(pid_t name) {
/// (Attempts to) stop all running child processes. /// (Attempts to) stop all running child processes.
void Util::Procs::StopAll() { void Util::Procs::StopAll() {
std::map<pid_t, std::string> listcopy = plist; std::set<pid_t> listcopy = plist;
std::map<pid_t, std::string>::iterator it; std::set<pid_t>::iterator it;
for (it = listcopy.begin(); it != listcopy.end(); it++) { for (it = listcopy.begin(); it != listcopy.end(); it++) {
Stop((*it).first); Stop(*it);
} }
} }
@ -684,54 +366,8 @@ int Util::Procs::Count() {
return plist.size(); return plist.size();
} }
/// Returns true if a process by this name is currently active.
bool Util::Procs::isActive(std::string name) {
std::map<pid_t, std::string> listcopy = plist;
std::map<pid_t, std::string>::iterator it;
for (it = listcopy.begin(); it != listcopy.end(); it++) {
if ((*it).second == name) {
if (childRunning((*it).first)) {
return true;
} else {
plist.erase((*it).first);
}
}
}
return false;
}
/// Returns true if a process with this PID is currently active. /// Returns true if a process with this PID is currently active.
bool Util::Procs::isActive(pid_t name) { bool Util::Procs::isActive(pid_t name) {
return (plist.count(name) == 1) && (kill(name, 0) == 0); return (plist.count(name) == 1) && (kill(name, 0) == 0);
} }
/// Gets PID for this named process, if active.
/// \return NULL if not active, process PID otherwise.
pid_t Util::Procs::getPid(std::string name) {
std::map<pid_t, std::string>::iterator it;
for (it = plist.begin(); it != plist.end(); it++) {
if ((*it).second == name) {
return (*it).first;
}
}
return 0;
}
/// Gets name for this process PID, if active.
/// \return Empty string if not active, name otherwise.
std::string Util::Procs::getName(pid_t name) {
if (plist.count(name) == 1) {
return plist[name];
}
return "";
}
/// Registers one notifier function for when a process indentified by PID terminates.
/// \return true if the notifier could be registered, false otherwise.
bool Util::Procs::SetTerminationNotifier(pid_t pid, TerminationNotifier notifier) {
if (plist.find(pid) != plist.end()) {
exitHandlers[pid] = notifier;
return true;
}
return false;
}

View file

@ -4,19 +4,16 @@
#pragma once #pragma once
#include <unistd.h> #include <unistd.h>
#include <string> #include <string>
#include <map> #include <set>
#include <vector> #include <vector>
/// Contains utility code, not directly related to streaming media /// Contains utility code, not directly related to streaming media
namespace Util { namespace Util {
typedef void (*TerminationNotifier)(pid_t pid, int exitCode);
/// Deals with spawning, monitoring and stopping child processes /// Deals with spawning, monitoring and stopping child processes
class Procs { class Procs {
private: private:
static std::map<pid_t, std::string> plist; ///< Holds active processes static std::set<pid_t> plist; ///< Holds active processes
static std::map<pid_t, TerminationNotifier> exitHandlers; ///< termination function, if any
static bool handler_set; ///< If true, the sigchld handler has been setup. static bool handler_set; ///< If true, the sigchld handler has been setup.
static void childsig_handler(int signum); static void childsig_handler(int signum);
static void exit_handler(); static void exit_handler();
@ -24,25 +21,13 @@ namespace Util {
static void setHandler(); static void setHandler();
public: public:
static std::string getOutputOf(char * const * argv); static std::string getOutputOf(char * const * argv);
static std::string getOutputOf(std::string cmd);
static pid_t Start(std::string name, std::string cmd);
static pid_t Start(std::string name, std::string cmd, std::string cmd2);
static pid_t Start(std::string name, std::string cmd, std::string cmd2, std::string cmd3);
static pid_t StartPiped(char * const * argv, int * fdin, int * fdout, int * fderr); static pid_t StartPiped(char * const * argv, int * fdin, int * fdout, int * fderr);
static pid_t StartPiped(std::string name, char * const * argv, int * fdin, int * fdout, int * fderr);
static pid_t StartPiped(std::string name, std::string cmd, int * fdin, int * fdout, int * fderr);
static pid_t StartPiped2(std::string name, std::string cmd1, std::string cmd2, int * fdin, int * fdout, int * fderr1, int * fderr2);
static void Stop(std::string name);
static void Stop(pid_t name); static void Stop(pid_t name);
static void Murder(pid_t name); static void Murder(pid_t name);
static void StopAll(); static void StopAll();
static int Count(); static int Count();
static bool isActive(std::string name);
static bool isActive(pid_t name); static bool isActive(pid_t name);
static bool isRunnning(pid_t pid); static bool isRunning(pid_t pid);
static pid_t getPid(std::string name);
static std::string getName(pid_t name);
static bool SetTerminationNotifier(pid_t pid, TerminationNotifier notifier);
}; };
} }

View file

@ -305,12 +305,12 @@ namespace IPC {
} while (i < 10 && !handle && autoBackoff); } while (i < 10 && !handle && autoBackoff);
} }
if (!handle) { if (!handle) {
FAIL_MSG("%s for page %s failed: %s", (master ? "CreateFileMapping" : "OpenFileMapping"), name.c_str(), strerror(errno)); FAIL_MSG("%s for page %s failed with error code %u", (master ? "CreateFileMapping" : "OpenFileMapping"), name.c_str(), GetLastError());
return; return;
} }
mapped = (char *)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0); mapped = (char *)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (!mapped) { if (!mapped) {
FAIL_MSG("MapViewOfFile for page %s failed: %s", name.c_str(), strerror(errno)); FAIL_MSG("MapViewOfFile for page %s failed with error code %u", name.c_str(), GetLastError());
return; return;
} }
//Under cygwin, the extra 4 bytes contain the real size of the page. //Under cygwin, the extra 4 bytes contain the real size of the page.
@ -740,7 +740,7 @@ namespace IPC {
DEBUG_MSG(DLVL_VERYHIGH, "Shared memory %s is now at count %u", baseName.c_str(), amount); DEBUG_MSG(DLVL_VERYHIGH, "Shared memory %s is now at count %u", baseName.c_str(), amount);
} }
unsigned short tmpPID = *((unsigned short *)(it->mapped+1+offset+payLen-2)); unsigned short tmpPID = *((unsigned short *)(it->mapped+1+offset+payLen-2));
if(!Util::Procs::isRunnning(tmpPID) && !(*counter == 126 || *counter == 127 || *counter == 254 || *counter == 255)){ if(!Util::Procs::isRunning(tmpPID) && !(*counter == 126 || *counter == 127 || *counter == 254 || *counter == 255)){
WARN_MSG("process disappeared, timing out. (pid %d)", tmpPID); WARN_MSG("process disappeared, timing out. (pid %d)", tmpPID);
*counter = 126; //if process is already dead, instant timeout. *counter = 126; //if process is already dead, instant timeout.
} }

View file

@ -18,21 +18,16 @@
///\brief Holds everything unique to the controller. ///\brief Holds everything unique to the controller.
namespace Controller { namespace Controller {
static std::map<long long, std::string> currentConnectors; ///<The currently running connectors. static std::map<std::string, pid_t> currentConnectors; ///<The currently running connectors.
static inline std::string toConn(long long i){
return std::string("Conn") + JSON::Value(i).asString();
}
///\brief Checks if the binary mentioned in the protocol argument is currently active, if so, restarts it. ///\brief Checks if the binary mentioned in the protocol argument is currently active, if so, restarts it.
///\param protocol The protocol to check. ///\param protocol The protocol to check.
void UpdateProtocol(std::string protocol){ void UpdateProtocol(std::string protocol){
std::map<long long, std::string>::iterator iter; std::map<std::string, pid_t>::iterator iter;
for (iter = currentConnectors.begin(); iter != currentConnectors.end(); iter++){ for (iter = currentConnectors.begin(); iter != currentConnectors.end(); iter++){
if (iter->second.substr(0, protocol.size()) == protocol){ if (iter->first.substr(0, protocol.size()) == protocol){
Log("CONF", "Killing connector for update: " + iter->second); Log("CONF", "Killing connector for update: " + iter->first);
Util::Procs::Stop(toConn(iter->first)); Util::Procs::Stop(iter->second);
} }
} }
} }
@ -65,7 +60,8 @@ namespace Controller {
} }
} }
static inline void buildPipedArguments(JSON::Value & p, char * argarr[], JSON::Value & capabilities){ static inline void buildPipedArguments(const std::string & proto, char * argarr[], JSON::Value & capabilities){
JSON::Value p = JSON::fromString(proto);
int argnum = 0; int argnum = 0;
static std::string tmparg; static std::string tmparg;
tmparg = Util::getMyPath() + std::string("MistOut") + p["connector"].asStringRef(); tmparg = Util::getMyPath() + std::string("MistOut") + p["connector"].asStringRef();
@ -82,12 +78,11 @@ namespace Controller {
if (pipedCapa.isMember("optional")){builPipedPart(p, argarr, argnum, pipedCapa["optional"]);} if (pipedCapa.isMember("optional")){builPipedPart(p, argarr, argnum, pipedCapa["optional"]);}
} }
///\brief Checks current protocol coguration, updates state of enabled connectors if neccesary. ///\brief Checks current protocol configuration, updates state of enabled connectors if neccessary.
///\param p An object containing all protocols. ///\param p An object containing all protocols.
///\param capabilities An object containing the detected capabilities. ///\param capabilities An object containing the detected capabilities.
void CheckProtocols(JSON::Value & p, JSON::Value & capabilities){ void CheckProtocols(JSON::Value & p, JSON::Value & capabilities){
std::map<long long, std::string> new_connectors; std::set<std::string> runningConns;
std::map<long long, std::string>::iterator iter;
// used for building args // used for building args
int zero = 0; int zero = 0;
@ -102,12 +97,13 @@ namespace Controller {
for (JSON::ArrIter ait = p.ArrBegin(); ait != p.ArrEnd(); ait++){ for (JSON::ArrIter ait = p.ArrBegin(); ait != p.ArrEnd(); ait++){
counter = ait - p.ArrBegin(); counter = ait - p.ArrBegin();
std::string prevOnline = ( *ait)["online"].asString(); std::string prevOnline = ( *ait)["online"].asString();
#define connName (*ait)["connector"].asStringRef() const std::string & connName = (*ait)["connector"].asStringRef();
//do not further parse if there's no connector name
if ( !(*ait).isMember("connector") || connName == ""){ if ( !(*ait).isMember("connector") || connName == ""){
( *ait)["online"] = "Missing connector name"; ( *ait)["online"] = "Missing connector name";
continue; continue;
} }
//ignore connectors that are not installed
if ( !capabilities["connectors"].isMember(connName)){ if ( !capabilities["connectors"].isMember(connName)){
( *ait)["online"] = "Not installed"; ( *ait)["online"] = "Not installed";
if (( *ait)["online"].asString() != prevOnline){ if (( *ait)["online"].asString() != prevOnline){
@ -115,14 +111,13 @@ namespace Controller {
} }
continue; continue;
} }
//list connectors that go through HTTP as 'enabled' without actually running them.
#define connCapa capabilities["connectors"][connName] JSON::Value & connCapa = capabilities["connectors"][connName];
if (connCapa.isMember("socket") || (connCapa.isMember("deps") && connCapa["deps"].asStringRef() == "HTTP")){ if (connCapa.isMember("socket") || (connCapa.isMember("deps") && connCapa["deps"].asStringRef() == "HTTP")){
( *ait)["online"] = "Enabled"; ( *ait)["online"] = "Enabled";
continue; continue;
} }
//check required parameters, skip if anything is missing
if (connCapa.isMember("required")){ if (connCapa.isMember("required")){
bool gotAll = true; bool gotAll = true;
for (JSON::ObjIter it = connCapa["required"].ObjBegin(); it != connCapa["required"].ObjEnd(); ++it){ for (JSON::ObjIter it = connCapa["required"].ObjBegin(); it != connCapa["required"].ObjEnd(); ++it){
@ -137,12 +132,13 @@ namespace Controller {
} }
if (!gotAll){continue;} if (!gotAll){continue;}
} }
//remove current online status
( *ait).removeMember("online"); ( *ait).removeMember("online");
/// \todo Check dependencies? /// \todo Check dependencies?
//set current online status
new_connectors[counter] = (*ait).toString(); std::string myCmd = (*ait).toString();
if (Util::Procs::isActive(toConn(counter))){ runningConns.insert(myCmd);
if (currentConnectors.count(myCmd) && Util::Procs::isActive(currentConnectors[myCmd])){
( *ait)["online"] = 1; ( *ait)["online"] = 1;
}else{ }else{
( *ait)["online"] = 0; ( *ait)["online"] = 0;
@ -150,28 +146,28 @@ namespace Controller {
} }
//shut down deleted/changed connectors //shut down deleted/changed connectors
for (iter = currentConnectors.begin(); iter != currentConnectors.end(); iter++){ std::map<std::string, pid_t>::iterator it;
if (new_connectors.count(iter->first) != 1 || new_connectors[iter->first] != iter->second){ for (it = currentConnectors.begin(); it != currentConnectors.end(); it++){
Log("CONF", "Stopping connector " + iter->second); if (!runningConns.count(it->first)){
Util::Procs::Stop(toConn(iter->first)); Log("CONF", "Stopping connector " + it->first);
Util::Procs::Stop(it->second);
} }
} }
//start up new/changed connectors //start up new/changed connectors
for (iter = new_connectors.begin(); iter != new_connectors.end(); iter++){ while (runningConns.size() && conf.is_active){
if (currentConnectors.count(iter->first) != 1 || currentConnectors[iter->first] != iter->second || !Util::Procs::isActive(toConn(iter->first))){ if (!currentConnectors.count(*runningConns.begin()) || !Util::Procs::isActive(currentConnectors[*runningConns.begin()])){
Log("CONF", "Starting connector: " + iter->second); Log("CONF", "Starting connector: " + *runningConns.begin());
// clear out old args // clear out old args
for (i=0; i<15; i++){argarr[i] = 0;} for (i=0; i<15; i++){argarr[i] = 0;}
// get args for this connector // get args for this connector
buildPipedArguments(p[(long long unsigned)iter->first], (char **)&argarr, capabilities); buildPipedArguments(*runningConns.begin(), (char **)&argarr, capabilities);
// start piped w/ generated args // start piped w/ generated args
Util::Procs::StartPiped(toConn(iter->first), argarr, &zero, &out, &err);//redirects output to out. Must make a new pipe, redirect std err currentConnectors[*runningConns.begin()] = Util::Procs::StartPiped(argarr, &zero, &out, &err);
} }
runningConns.erase(runningConns.begin());
} }
//store new state
currentConnectors = new_connectors;
} }
} }