Merge branch 'development' into LTS_development

# Conflicts:
#	lib/shared_memory.cpp
#	src/controller/controller.cpp
#	src/controller/controller_storage.h
#	src/output/output.cpp
This commit is contained in:
Thulinma 2016-09-15 16:17:06 +02:00
commit 1172768c34
20 changed files with 270 additions and 192 deletions

View file

@ -34,6 +34,7 @@
#include <ctime>
#include <vector>
#include <sys/stat.h>
#include <sys/wait.h>
#include <mist/config.h>
#include <mist/socket.h>
#include <mist/http_parser.h>
@ -95,6 +96,7 @@ void createAccount (std::string account){
}
}
/// Status monitoring thread.
/// Will check outputs, inputs and converters every five seconds
void statusMonitor(void * np){
@ -138,15 +140,14 @@ void statusMonitor(void * np){
configLock.unlink();
}
///\brief The main entry point for the controller.
///\brief The main loop for the controller.
///
/// \triggers
/// The `"SYSTEM_STOP"` trigger is global, and is ran when the controller shuts down. If cancelled, the controller does not shut down and will attempt to re-open the API socket. Its payload is:
/// ~~~~~~~~~~~~~~~
/// shutdown reason
/// ~~~~~~~~~~~~~~~
int main(int argc, char ** argv){
int main_loop(int argc, char ** argv){
Controller::Storage = JSON::fromFile("config.json");
JSON::Value stored_port = JSON::fromString("{\"long\":\"port\", \"short\":\"p\", \"arg\":\"integer\", \"help\":\"TCP port to listen on.\"}");
stored_port["default"] = Controller::Storage["config"]["controller"]["port"];
@ -163,7 +164,6 @@ int main(int argc, char ** argv){
if ( !stored_user["default"]){
stored_user["default"] = "root";
}
Controller::conf = Util::Config(argv[0]);
Controller::conf.addOption("port", stored_port);
Controller::conf.addOption("interface", stored_interface);
Controller::conf.addOption("username", stored_user);
@ -205,6 +205,7 @@ int main(int argc, char ** argv){
if (pipe(pipeErr) >= 0){
dup2(pipeErr[1], STDERR_FILENO);//cause stderr to write to the pipe
close(pipeErr[1]);//close the unneeded pipe file descriptor
Util::Procs::socketList.insert(pipeErr[0]);
tthread::thread msghandler(Controller::handleMsg, (void*)(((char*)0) + pipeErr[0]));
msghandler.detach();
}
@ -262,7 +263,7 @@ int main(int argc, char ** argv){
}
}else if(yna(in_string) == 'a'){
//abort controller startup
return 0;
return 1;
}
}
}
@ -284,7 +285,7 @@ int main(int argc, char ** argv){
}
}else if(yna(in_string) == 'a'){
//abort controller startup
return 0;
return 1;
}
}
}
@ -334,10 +335,10 @@ int main(int argc, char ** argv){
}else{
shutdown_reason = "socket problem (API port closed)";
}
/*LTS-START*/
if (Controller::restarting){
shutdown_reason = "update (on request)";
shutdown_reason = "restart (on request)";
}
/*LTS-START*/
if(Triggers::shouldTrigger("SYSTEM_STOP")){
if (!Triggers::doTrigger("SYSTEM_STOP", shutdown_reason)){
Controller::conf.is_active = true;
@ -348,8 +349,10 @@ int main(int argc, char ** argv){
Controller::Log("CONF", "Controller shutting down because of "+shutdown_reason);
}
}else{
/*LTS-END*/
Controller::conf.is_active = false;
Controller::Log("CONF", "Controller shutting down because of "+shutdown_reason);
/*LTS-START*/
}
}//indentation intentionally wrong, to minimize Pro/nonPro diffs
/*LTS-END*/
@ -374,16 +377,85 @@ int main(int argc, char ** argv){
Util::Procs::StopAll();
//give everything some time to print messages
Util::wait(100);
std::cout << "Killed all processes, wrote config to disk. Exiting." << std::endl;
if (Controller::restarting){
return 42;
}
//close stderr to make the stderr reading thread exit
close(STDERR_FILENO);
std::cout << "Killed all processes, wrote config to disk. Exiting." << std::endl;
/*LTS-START*/
if (Controller::restarting){
std::string myFile = Util::getMyPath() + "MistController";
execvp(myFile.c_str(), argv);
std::cout << "Error restarting: " << strerror(errno) << std::endl;
}
/*LTS-END*/
return 0;
}
void handleUSR1(int signum, siginfo_t * sigInfo, void * ignore){
Controller::Log("CONF", "USR1 received - restarting controller");
Controller::restarting = true;
raise(SIGINT); //trigger restart
}
///\brief The controller angel process.
///Starts a forked main_loop in a loop. Yes, you read that right.
int main(int argc, char ** argv){
Util::Procs::setHandler();//set child handler
{
struct sigaction new_action;
struct sigaction cur_action;
new_action.sa_sigaction = handleUSR1;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGUSR1, &new_action, NULL);
}
Controller::conf = Util::Config(argv[0]);
Controller::conf.activate();
uint64_t reTimer = 0;
while (Controller::conf.is_active){
pid_t pid = fork();
if (pid == 0){
Util::Procs::handler_set = false;
Util::Procs::reaper_thread = 0;
{
struct sigaction new_action;
struct sigaction cur_action;
new_action.sa_sigaction = handleUSR1;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGUSR1, &new_action, NULL);
}
return main_loop(argc, argv);
}
if (pid == -1){
FAIL_MSG("Unable to spawn controller process!");
return 2;
}
//wait for the process to exit
int status;
while (waitpid(pid, &status, 0) != pid && errno == EINTR){
if (Controller::restarting){
Controller::conf.is_active = true;
Controller::restarting = false;
kill(pid, SIGUSR1);
}
if (!Controller::conf.is_active){
INFO_MSG("Shutting down controller because of signal interrupt...");
Util::Procs::Stop(pid);
}
continue;
}
//if the exit was clean, don't restart it
if (WIFEXITED(status) && (WEXITSTATUS(status) == 0)){
MEDIUM_MSG("Controller shut down cleanly");
break;
}
if (WIFEXITED(status) && (WEXITSTATUS(status) == 42)){
WARN_MSG("Refreshing angel process for update");
std::string myFile = Util::getMyPath() + "MistController";
execvp(myFile.c_str(), argv);
FAIL_MSG("Error restarting: %s", strerror(errno));
}
INFO_MSG("Controller uncleanly shut down! Restarting in %llu...", reTimer);
Util::wait(reTimer);
reTimer += 1000;
}
return 0;
}

View file

@ -18,6 +18,7 @@ namespace Controller {
tthread::mutex logMutex;
unsigned long long logCounter = 0;
bool configChanged = false;
bool restarting = false;
///\brief Store and print a log message.
///\param kind The type of message.

View file

@ -9,6 +9,7 @@ namespace Controller {
extern tthread::mutex logMutex;///< Mutex for log thread.
extern tthread::mutex configMutex;///< Mutex for server config access.
extern bool configChanged; ///< Bool that indicates config must be written to SHM.
extern bool restarting;///< Signals if the controller is shutting down (false) or restarting (true).
extern unsigned long long logCounter; ///<Count of logged messages since boot
/// Store and print a log message.

View file

@ -18,7 +18,6 @@
#include "controller_updater.h"
namespace Controller {
bool restarting = false;
JSON::Value updates;
std::string uniqId;

View file

@ -8,7 +8,6 @@
#endif
namespace Controller {
extern bool restarting;///< Signals if the controller is shutting down (false) or restarting (true).
extern JSON::Value updates;
extern std::string uniqId;