diff --git a/src/Deployment.cpp b/src/Deployment.cpp index 21099bb..bd29d73 100644 --- a/src/Deployment.cpp +++ b/src/Deployment.cpp @@ -140,6 +140,11 @@ const std::vector< std::string >& Deployment::getTaskNames() const return tasks; } +const std::map& Deployment::getRenameMap() const +{ + return renameMap; +} + const std::vector< std::string >& Deployment::getNeededTypekits() const { return typekits; diff --git a/src/Deployment.hpp b/src/Deployment.hpp index 9f425a0..f45d379 100644 --- a/src/Deployment.hpp +++ b/src/Deployment.hpp @@ -44,6 +44,8 @@ class Deployment : public boost::noncopyable * */ const std::vector &getTaskNames() const; + const std::map &getRenameMap() const; + const std::vector &getNeededTypekits() const; /** diff --git a/src/LoggingHelper.cpp b/src/LoggingHelper.cpp index 2a4925e..f31be3e 100644 --- a/src/LoggingHelper.cpp +++ b/src/LoggingHelper.cpp @@ -28,7 +28,7 @@ bool LoggingHelper::logTasks() bool LoggingHelper::logTasks(const std::map &loggingEnabledTaskMap, bool logAll) { - Spawner &spawner(Spawner::getInstace()); + Spawner &spawner(Spawner::getInstance()); std::vector depls = spawner.getRunningDeployments(); @@ -89,7 +89,7 @@ bool LoggingHelper::logTasks(const std::map &loggingEnabledTa bool LoggingHelper::logTasks(const std::vector< std::string >& excludeList) { - Spawner &spawner(Spawner::getInstace()); + Spawner &spawner(Spawner::getInstance()); std::vector depls = spawner.getRunningDeployments(); diff --git a/src/Spawner.cpp b/src/Spawner.cpp index 2965644..bb3fce3 100644 --- a/src/Spawner.cpp +++ b/src/Spawner.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,7 @@ void shutdownHandler(int signum, siginfo_t *info, void *data) std::cout << "Shutdown: trying to kill all childs" << std::endl; try { - Spawner::getInstace().killAll(); + Spawner::getInstance().killAll(); std::cout << "Done " << std::endl; } catch (...) { @@ -79,7 +80,7 @@ Spawner::Spawner() setSignalHandler(SIGTERM); } -Spawner& Spawner::getInstace() +Spawner& Spawner::getInstance() { static Spawner *instance = nullptr; @@ -92,7 +93,7 @@ Spawner& Spawner::getInstace() } -Spawner::ProcessHandle::ProcessHandle(Deployment *deploment, bool redirectOutputv, const std::string &logDir) : isRunning(true), deployment(deploment) +Spawner::ProcessHandle::ProcessHandle(Deployment *deploment, bool redirectOutputv, const std::string &logDir) : deployment(deploment) { std::string cmd; std::vector< std::string > args; @@ -178,55 +179,31 @@ Spawner::ProcessHandle::ProcessHandle(Deployment *deploment, bool redirectOutput bool Spawner::ProcessHandle::alive() const { - //if it was already determined before that the process is already dead, - //we can stop here. Otherwise waitpid would fail! - if(!isRunning){ - return isRunning; - } - int status = 0; pid_t ret = waitpid(pid, &status, WNOHANG); - if(ret < 0 ) - { - throw std::runtime_error(std::string("WaitPid failed ") + strerror(errno)); - } - - if(!status) - { - return isRunning; - } - - if(WIFEXITED(status)) - { - int exitStatus = WEXITSTATUS(status); - std::cout << "Process " << pid << " terminated normaly, return code " << exitStatus << std::endl; - isRunning = false; - } - - if(WIFSIGNALED(status)) + if(ret == 0) + return true; + else if(ret == pid) + return false; + else if(ret == -1 ) + throw std::runtime_error(std::string("waitpid failed: ") + strerror(errno)); + else + throw std::runtime_error("waitpid returned undocumented value"); +} + +bool Spawner::ProcessHandle::wait(int cycles, int usecs_between_cycles) const +{ + while(alive()) { - isRunning = false; - - int sigNum = WTERMSIG(status); - - if(sigNum == SIGSEGV) - { - - std::cout << "Process " << processName << " segfaulted " << std::endl; - } - else - { - std::cout << "Process " << processName << " was terminated by SIG " << sigNum << std::endl; - } - + usleep(usecs_between_cycles); + cycles --; + if(cycles <= 0) + return false; } - - return isRunning; + return true; } - - const Deployment& Spawner::ProcessHandle::getDeployment() const { return *deployment; @@ -256,8 +233,6 @@ void Spawner::ProcessHandle::sendSigTerm() const } } - - Spawner::ProcessHandle &Spawner::spawnTask(const std::string& cmp1, const std::string& as, bool redirectOutput) { Deployment *dpl = new Deployment(cmp1, as); @@ -272,6 +247,13 @@ Spawner::ProcessHandle& Spawner::spawnDeployment(Deployment* deployment, bool re logDir = Bundle::getInstance().getLogDirectory(); } + // rename the logger of default deployments + // this guarantees that every task has it's own logger + if(deployment->getName().find("orogen_default_") == 0) + { + deployment->renameTask(deployment->getLoggerName(), deployment->getName() + "_Logger"); + } + ProcessHandle *handle = new ProcessHandle(deployment, redirectOutput, logDir); handles.push_back(handle); @@ -284,6 +266,16 @@ Spawner::ProcessHandle& Spawner::spawnDeployment(Deployment* deployment, bool re return *handle; } +Spawner::ProcessHandle& Spawner::getDeployment(const std::string& dplName) +{ + for(Spawner::ProcessHandle* h : handles) + { + if(h->getDeployment().getName() == dplName) + return *h; + } + throw std::runtime_error(std::string("Deployment does not exist: ") + dplName); +} + Spawner::ProcessHandle& Spawner::spawnDeployment(const std::string& dplName, bool redirectOutput) { Deployment *deploment = new Deployment(dplName); @@ -344,6 +336,24 @@ void Spawner::waitUntilAllReady(const base::Time& timeout) } } +bool Spawner::killDeployment(const std::string &dplName) +{ + Spawner::ProcessHandle &handle = getDeployment(dplName); + + handle.sendSigInt(); + if(!handle.wait()) + { + std::cout << "Failed to terminate deployment '" << dplName << "', trying to kill..." << std::endl; + handle.sendSigKill(); + if(!handle.wait()) + { + std::cout << "Failed to kill deployment '" << dplName << "'." << std::endl; + return false; + } + } + return true; +} + void Spawner::killAll() { //first we try to stop and cleanup the processes diff --git a/src/Spawner.hpp b/src/Spawner.hpp index 126117f..0969f93 100644 --- a/src/Spawner.hpp +++ b/src/Spawner.hpp @@ -30,7 +30,6 @@ class Spawner : public boost::noncopyable public: class ProcessHandle { - mutable bool isRunning; pid_t pid; void redirectOutput(const std::string &filename); std::string processName; @@ -41,6 +40,7 @@ class Spawner : public boost::noncopyable const Deployment &getDeployment() const; bool alive() const; + bool wait(int cycles=500, int usecs_between_cycles=500) const; void sendSigInt() const; void sendSigTerm() const; void sendSigKill() const; @@ -52,7 +52,7 @@ class Spawner : public boost::noncopyable * Singleton pattern, returns the ONE instance of * the spawner. * */ - static Spawner &getInstace(); + static Spawner &getInstance(); /** * This method spawns a default deployment matching the given componente description. @@ -85,6 +85,12 @@ class Spawner : public boost::noncopyable * */ ProcessHandle &spawnDeployment(Deployment *deployment, bool redirectOutput = true); + /** + * Get a deployment by its name + * @arg dplName + */ + ProcessHandle &getDeployment(const std::string &dplName); + /** * This method checks if all spawened processes are still alive * @return false if any process died @@ -105,6 +111,12 @@ class Spawner : public boost::noncopyable * */ void waitUntilAllReady(const base::Time &timeout); + /** + * Kill deployment with the given name + * @arg dplName + */ + bool killDeployment(const std::string &dplName); + /** * This method first sends a sigterm to all processes * and waits for the processes to terminate. If this diff --git a/src/main3.cpp b/src/main3.cpp index 398502a..a95af6e 100644 --- a/src/main3.cpp +++ b/src/main3.cpp @@ -15,7 +15,7 @@ int main(int argc, char**argv) PluginHelper::loadAllPluginsInDir("/home/scotch/coyote/install/lib/orocos/gnulinux/types/"); PluginHelper::loadAllPluginsInDir("/home/scotch/coyote/install/lib/orocos/types/"); - Spawner &spawner(Spawner::getInstace()); + Spawner &spawner(Spawner::getInstance()); spawner.spawnTask("hokuyo::Task", "hokuyo");