Generalized Util::Config::is_restarting for rolling restarts, added rolling restart support to listening socket outputs
This commit is contained in:
parent
26c9f964be
commit
5418c1fefc
11 changed files with 74 additions and 26 deletions
|
@ -35,6 +35,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
bool Util::Config::is_active = false;
|
bool Util::Config::is_active = false;
|
||||||
|
bool Util::Config::is_restarting = false;
|
||||||
static Socket::Server *serv_sock_pointer = 0;
|
static Socket::Server *serv_sock_pointer = 0;
|
||||||
uint32_t Util::Config::printDebugLevel = DEBUG; //
|
uint32_t Util::Config::printDebugLevel = DEBUG; //
|
||||||
std::string Util::Config::streamName;
|
std::string Util::Config::streamName;
|
||||||
|
@ -350,16 +351,19 @@ int Util::Config::forkServer(Socket::Server &server_socket, int (*callback)(Sock
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Util::Procs::socketList.erase(server_socket.getSocket());
|
Util::Procs::socketList.erase(server_socket.getSocket());
|
||||||
|
if (!is_restarting){
|
||||||
server_socket.close();
|
server_socket.close();
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)){
|
int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)){
|
||||||
Socket::Server server_socket;
|
Socket::Server server_socket;
|
||||||
if (vals.isMember("socket")){
|
if (Socket::checkTrueSocket(0)){
|
||||||
|
server_socket = Socket::Server(0);
|
||||||
|
}else if (vals.isMember("socket")){
|
||||||
server_socket = Socket::Server(Util::getTmpFolder() + getString("socket"));
|
server_socket = Socket::Server(Util::getTmpFolder() + getString("socket"));
|
||||||
}
|
} else if (vals.isMember("port") && vals.isMember("interface")){
|
||||||
if (vals.isMember("port") && vals.isMember("interface")){
|
|
||||||
server_socket = Socket::Server(getInteger("port"), getString("interface"), false);
|
server_socket = Socket::Server(getInteger("port"), getString("interface"), false);
|
||||||
}
|
}
|
||||||
if (!server_socket.connected()){
|
if (!server_socket.connected()){
|
||||||
|
@ -369,6 +373,13 @@ int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)){
|
||||||
serv_sock_pointer = &server_socket;
|
serv_sock_pointer = &server_socket;
|
||||||
DEVEL_MSG("Activating threaded server: %s", getString("cmd").c_str());
|
DEVEL_MSG("Activating threaded server: %s", getString("cmd").c_str());
|
||||||
activate();
|
activate();
|
||||||
|
if (server_socket.getSocket()){
|
||||||
|
int oldSock = server_socket.getSocket();
|
||||||
|
if (!dup2(oldSock, 0)){
|
||||||
|
server_socket = Socket::Server(0);
|
||||||
|
close(oldSock);
|
||||||
|
}
|
||||||
|
}
|
||||||
int r = threadServer(server_socket, callback);
|
int r = threadServer(server_socket, callback);
|
||||||
serv_sock_pointer = 0;
|
serv_sock_pointer = 0;
|
||||||
return r;
|
return r;
|
||||||
|
@ -376,10 +387,11 @@ int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)){
|
||||||
|
|
||||||
int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection &S)){
|
int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection &S)){
|
||||||
Socket::Server server_socket;
|
Socket::Server server_socket;
|
||||||
if (vals.isMember("socket")){
|
if (Socket::checkTrueSocket(0)){
|
||||||
|
server_socket = Socket::Server(0);
|
||||||
|
}else if (vals.isMember("socket")){
|
||||||
server_socket = Socket::Server(Util::getTmpFolder() + getString("socket"));
|
server_socket = Socket::Server(Util::getTmpFolder() + getString("socket"));
|
||||||
}
|
} else if (vals.isMember("port") && vals.isMember("interface")){
|
||||||
if (vals.isMember("port") && vals.isMember("interface")){
|
|
||||||
server_socket = Socket::Server(getInteger("port"), getString("interface"), false);
|
server_socket = Socket::Server(getInteger("port"), getString("interface"), false);
|
||||||
}
|
}
|
||||||
if (!server_socket.connected()){
|
if (!server_socket.connected()){
|
||||||
|
@ -389,6 +401,13 @@ int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection &S)){
|
||||||
serv_sock_pointer = &server_socket;
|
serv_sock_pointer = &server_socket;
|
||||||
DEVEL_MSG("Activating forked server: %s", getString("cmd").c_str());
|
DEVEL_MSG("Activating forked server: %s", getString("cmd").c_str());
|
||||||
activate();
|
activate();
|
||||||
|
if (server_socket.getSocket()){
|
||||||
|
int oldSock = server_socket.getSocket();
|
||||||
|
if (!dup2(oldSock, 0)){
|
||||||
|
server_socket = Socket::Server(0);
|
||||||
|
close(oldSock);
|
||||||
|
}
|
||||||
|
}
|
||||||
int r = forkServer(server_socket, callback);
|
int r = forkServer(server_socket, callback);
|
||||||
serv_sock_pointer = 0;
|
serv_sock_pointer = 0;
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace Util{
|
||||||
public:
|
public:
|
||||||
// variables
|
// variables
|
||||||
static bool is_active; ///< Set to true by activate(), set to false by the signal handler.
|
static bool is_active; ///< Set to true by activate(), set to false by the signal handler.
|
||||||
|
static bool is_restarting; ///< Set to true when restarting, set to false on boot.
|
||||||
static uint32_t printDebugLevel;
|
static uint32_t printDebugLevel;
|
||||||
static std::string streamName; ///< Used by debug messages to identify the stream name
|
static std::string streamName; ///< Used by debug messages to identify the stream name
|
||||||
// functions
|
// functions
|
||||||
|
|
|
@ -58,6 +58,13 @@ bool Socket::isLocalhost(const std::string &remotehost){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Checks if the given file descriptor is actually socket or not.
|
||||||
|
bool Socket::checkTrueSocket(int sock){
|
||||||
|
struct stat sBuf;
|
||||||
|
if (sock != -1 && !fstat(sock, &sBuf)){return S_ISSOCK(sBuf.st_mode);}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Socket::isLocal(const std::string &remotehost){
|
bool Socket::isLocal(const std::string &remotehost){
|
||||||
struct ifaddrs *ifAddrStruct = NULL;
|
struct ifaddrs *ifAddrStruct = NULL;
|
||||||
struct ifaddrs *ifa = NULL;
|
struct ifaddrs *ifa = NULL;
|
||||||
|
@ -400,9 +407,7 @@ void Socket::Connection::setBoundAddr(){
|
||||||
Socket::Connection::Connection(int sockNo){
|
Socket::Connection::Connection(int sockNo){
|
||||||
sSend = sockNo;
|
sSend = sockNo;
|
||||||
sRecv = -1;
|
sRecv = -1;
|
||||||
isTrueSocket = false;
|
isTrueSocket = Socket::checkTrueSocket(sSend);
|
||||||
struct stat sBuf;
|
|
||||||
if (sSend != -1 && !fstat(sSend, &sBuf)){isTrueSocket = S_ISSOCK(sBuf.st_mode);}
|
|
||||||
setBoundAddr();
|
setBoundAddr();
|
||||||
up = 0;
|
up = 0;
|
||||||
down = 0;
|
down = 0;
|
||||||
|
@ -422,9 +427,7 @@ Socket::Connection::Connection(int write, int read){
|
||||||
}else{
|
}else{
|
||||||
sRecv = -1;
|
sRecv = -1;
|
||||||
}
|
}
|
||||||
isTrueSocket = false;
|
isTrueSocket = Socket::checkTrueSocket(sSend);
|
||||||
struct stat sBuf;
|
|
||||||
if (sSend != -1 && !fstat(sSend, &sBuf)){isTrueSocket = S_ISSOCK(sBuf.st_mode);}
|
|
||||||
setBoundAddr();
|
setBoundAddr();
|
||||||
up = 0;
|
up = 0;
|
||||||
down = 0;
|
down = 0;
|
||||||
|
@ -1089,6 +1092,11 @@ Socket::Server::Server(){
|
||||||
sock = -1;
|
sock = -1;
|
||||||
}// Socket::Server base Constructor
|
}// Socket::Server base Constructor
|
||||||
|
|
||||||
|
/// Create a new Server from existing socket.
|
||||||
|
Socket::Server::Server(int fromSock){
|
||||||
|
sock = fromSock;
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a new TCP Server. The socket is immediately bound and set to listen.
|
/// Create a new TCP Server. The socket is immediately bound and set to listen.
|
||||||
/// A maximum of 100 connections will be accepted between accept() calls.
|
/// A maximum of 100 connections will be accepted between accept() calls.
|
||||||
/// Any further connections coming in will be dropped.
|
/// Any further connections coming in will be dropped.
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace Socket{
|
||||||
bool isLocal(const std::string & host);
|
bool isLocal(const std::string & host);
|
||||||
/// Returns true if given human-readable hostname is a local address.
|
/// Returns true if given human-readable hostname is a local address.
|
||||||
bool isLocalhost(const std::string & host);
|
bool isLocalhost(const std::string & host);
|
||||||
|
bool checkTrueSocket(int sock);
|
||||||
|
|
||||||
/// A buffer made out of std::string objects that can be efficiently read from and written to.
|
/// A buffer made out of std::string objects that can be efficiently read from and written to.
|
||||||
class Buffer{
|
class Buffer{
|
||||||
|
@ -165,7 +166,8 @@ namespace Socket{
|
||||||
bool IPv4bind(int port, std::string hostname, bool nonblock); ///< Attempt to bind an IPv4 socket
|
bool IPv4bind(int port, std::string hostname, bool nonblock); ///< Attempt to bind an IPv4 socket
|
||||||
public:
|
public:
|
||||||
Server(); ///< Create a new base Server.
|
Server(); ///< Create a new base Server.
|
||||||
Server(int port, std::string hostname = "0.0.0.0", bool nonblock = false); ///< Create a new TCP Server.
|
Server(int existingSock); ///< Create a new Server from existing socket.
|
||||||
|
Server(int port, std::string hostname, bool nonblock = false); ///< Create a new TCP Server.
|
||||||
Server(std::string adres, bool nonblock = false); ///< Create a new Unix Server.
|
Server(std::string adres, bool nonblock = false); ///< Create a new Unix Server.
|
||||||
Connection accept(bool nonblock = false); ///< Accept any waiting connections.
|
Connection accept(bool nonblock = false); ///< Accept any waiting connections.
|
||||||
void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false).
|
void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false).
|
||||||
|
|
|
@ -86,7 +86,7 @@ void statusMonitor(void *np){
|
||||||
}
|
}
|
||||||
Util::sleep(3000); // wait at least 3 seconds
|
Util::sleep(3000); // wait at least 3 seconds
|
||||||
}
|
}
|
||||||
if (Controller::restarting){
|
if (Util::Config::is_restarting){
|
||||||
Controller::prepareActiveConnectorsForReload();
|
Controller::prepareActiveConnectorsForReload();
|
||||||
}else{
|
}else{
|
||||||
Controller::prepareActiveConnectorsForShutdown();
|
Controller::prepareActiveConnectorsForShutdown();
|
||||||
|
@ -457,7 +457,7 @@ int main_loop(int argc, char **argv){
|
||||||
}else{
|
}else{
|
||||||
shutdown_reason = "socket problem (API port closed)";
|
shutdown_reason = "socket problem (API port closed)";
|
||||||
}
|
}
|
||||||
if (Controller::restarting){shutdown_reason = "restart (on request)";}
|
if (Util::Config::is_restarting){shutdown_reason = "restart (on request)";}
|
||||||
/*LTS-START*/
|
/*LTS-START*/
|
||||||
#ifdef LICENSING
|
#ifdef LICENSING
|
||||||
if (!Controller::isLicensed()){shutdown_reason = "no valid license";}
|
if (!Controller::isLicensed()){shutdown_reason = "no valid license";}
|
||||||
|
@ -465,7 +465,7 @@ int main_loop(int argc, char **argv){
|
||||||
if (Triggers::shouldTrigger("SYSTEM_STOP")){
|
if (Triggers::shouldTrigger("SYSTEM_STOP")){
|
||||||
if (!Triggers::doTrigger("SYSTEM_STOP", shutdown_reason)){
|
if (!Triggers::doTrigger("SYSTEM_STOP", shutdown_reason)){
|
||||||
Controller::conf.is_active = true;
|
Controller::conf.is_active = true;
|
||||||
Controller::restarting = false;
|
Util::Config::is_restarting = false;
|
||||||
Util::sleep(1000);
|
Util::sleep(1000);
|
||||||
}else{
|
}else{
|
||||||
Controller::conf.is_active = false;
|
Controller::conf.is_active = false;
|
||||||
|
@ -513,7 +513,7 @@ int main_loop(int argc, char **argv){
|
||||||
<< " seconds, on license server request..." << std::endl;
|
<< " seconds, on license server request..." << std::endl;
|
||||||
while (Controller::exitDelay--){Util::wait(1000);}
|
while (Controller::exitDelay--){Util::wait(1000);}
|
||||||
}
|
}
|
||||||
if (Controller::restarting){return 42;}
|
if (Util::Config::is_restarting){return 42;}
|
||||||
// close stderr to make the stderr reading thread exit
|
// close stderr to make the stderr reading thread exit
|
||||||
close(STDERR_FILENO);
|
close(STDERR_FILENO);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -521,7 +521,7 @@ int main_loop(int argc, char **argv){
|
||||||
|
|
||||||
void handleUSR1(int signum, siginfo_t *sigInfo, void *ignore){
|
void handleUSR1(int signum, siginfo_t *sigInfo, void *ignore){
|
||||||
Controller::Log("CONF", "USR1 received - restarting controller");
|
Controller::Log("CONF", "USR1 received - restarting controller");
|
||||||
Controller::restarting = true;
|
Util::Config::is_restarting = true;
|
||||||
raise(SIGINT); // trigger restart
|
raise(SIGINT); // trigger restart
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,9 +561,9 @@ int main(int argc, char **argv){
|
||||||
// wait for the process to exit
|
// wait for the process to exit
|
||||||
int status;
|
int status;
|
||||||
while (waitpid(pid, &status, 0) != pid && errno == EINTR){
|
while (waitpid(pid, &status, 0) != pid && errno == EINTR){
|
||||||
if (Controller::restarting){
|
if (Util::Config::is_restarting){
|
||||||
Controller::conf.is_active = true;
|
Controller::conf.is_active = true;
|
||||||
Controller::restarting = false;
|
Util::Config::is_restarting = false;
|
||||||
kill(pid, SIGUSR1);
|
kill(pid, SIGUSR1);
|
||||||
}
|
}
|
||||||
if (!Controller::conf.is_active){
|
if (!Controller::conf.is_active){
|
||||||
|
|
|
@ -51,11 +51,13 @@ namespace Controller {
|
||||||
IPC::sharedPage f("MstCnns", 4096, false, false);
|
IPC::sharedPage f("MstCnns", 4096, false, false);
|
||||||
const Util::RelAccX A(f.mapped, false);
|
const Util::RelAccX A(f.mapped, false);
|
||||||
if (A.isReady()){
|
if (A.isReady()){
|
||||||
|
INFO_MSG("Reloading existing connectors to complete rolling restart");
|
||||||
for (uint32_t i = 0; i < A.getRCount(); ++i){
|
for (uint32_t i = 0; i < A.getRCount(); ++i){
|
||||||
char * p = A.getPointer("cmd", i);
|
char * p = A.getPointer("cmd", i);
|
||||||
if (p != 0 && p[0] != 0){
|
if (p != 0 && p[0] != 0){
|
||||||
currentConnectors[p] = A.getInt("pid", i);
|
currentConnectors[p] = A.getInt("pid", i);
|
||||||
Util::Procs::remember(A.getInt("pid", i));
|
Util::Procs::remember(A.getInt("pid", i));
|
||||||
|
kill(A.getInt("pid", i), SIGUSR1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,7 +202,7 @@ namespace Controller{
|
||||||
Util::wait(1000); // wait at least a second
|
Util::wait(1000); // wait at least a second
|
||||||
}
|
}
|
||||||
//keep the pushPage if we are restarting, so we can restore state from it
|
//keep the pushPage if we are restarting, so we can restore state from it
|
||||||
if (Controller::restarting){
|
if (Util::Config::is_restarting){
|
||||||
pushPage.master = false;
|
pushPage.master = false;
|
||||||
//forget about all pushes, so they keep running
|
//forget about all pushes, so they keep running
|
||||||
for (std::map<pid_t, JSON::Value>::iterator it = activePushes.begin(); it != activePushes.end(); ++it){
|
for (std::map<pid_t, JSON::Value>::iterator it = activePushes.begin(); it != activePushes.end(); ++it){
|
||||||
|
|
|
@ -433,7 +433,7 @@ void Controller::SharedMemStats(void * config){
|
||||||
}
|
}
|
||||||
statPointer = 0;
|
statPointer = 0;
|
||||||
HIGH_MSG("Stopping stats thread");
|
HIGH_MSG("Stopping stats thread");
|
||||||
if (Controller::restarting){
|
if (Util::Config::is_restarting){
|
||||||
statServer.abandon();
|
statServer.abandon();
|
||||||
shmSessions->master = false;
|
shmSessions->master = false;
|
||||||
}else{/*LTS-START*/
|
}else{/*LTS-START*/
|
||||||
|
@ -443,7 +443,7 @@ void Controller::SharedMemStats(void * config){
|
||||||
}
|
}
|
||||||
/*LTS-END*/
|
/*LTS-END*/
|
||||||
}
|
}
|
||||||
Controller::deinitState(Controller::restarting);
|
Controller::deinitState(Util::Config::is_restarting);
|
||||||
delete shmSessions;
|
delete shmSessions;
|
||||||
shmSessions = 0;
|
shmSessions = 0;
|
||||||
delete cacheLock;
|
delete cacheLock;
|
||||||
|
|
|
@ -21,7 +21,6 @@ namespace Controller{
|
||||||
tthread::mutex logMutex;
|
tthread::mutex logMutex;
|
||||||
uint64_t logCounter = 0;
|
uint64_t logCounter = 0;
|
||||||
bool configChanged = false;
|
bool configChanged = false;
|
||||||
bool restarting = false;
|
|
||||||
bool isTerminal = false;
|
bool isTerminal = false;
|
||||||
bool isColorized = false;
|
bool isColorized = false;
|
||||||
uint32_t maxLogsRecs = 0;
|
uint32_t maxLogsRecs = 0;
|
||||||
|
|
|
@ -13,7 +13,6 @@ namespace Controller {
|
||||||
extern tthread::mutex logMutex;///< Mutex for log thread.
|
extern tthread::mutex logMutex;///< Mutex for log thread.
|
||||||
extern tthread::mutex configMutex;///< Mutex for server config access.
|
extern tthread::mutex configMutex;///< Mutex for server config access.
|
||||||
extern bool configChanged; ///< Bool that indicates config must be written to SHM.
|
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 bool isTerminal;///< True if connected to a terminal and not a log file.
|
extern bool isTerminal;///< True if connected to a terminal and not a log file.
|
||||||
extern bool isColorized;///< True if we colorize the output
|
extern bool isColorized;///< True if we colorize the output
|
||||||
extern uint64_t logCounter; ///<Count of logged messages since boot
|
extern uint64_t logCounter; ///<Count of logged messages since boot
|
||||||
|
|
|
@ -9,6 +9,12 @@ int spawnForked(Socket::Connection & S){
|
||||||
return tmp.run();
|
return tmp.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleUSR1(int signum, siginfo_t *sigInfo, void *ignore){
|
||||||
|
HIGH_MSG("USR1 received - triggering rolling restart");
|
||||||
|
Util::Config::is_restarting = true;
|
||||||
|
Util::Config::is_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
Util::redirectLogsIfNeeded();
|
Util::redirectLogsIfNeeded();
|
||||||
Util::Config conf(argv[0]);
|
Util::Config conf(argv[0]);
|
||||||
|
@ -21,7 +27,19 @@ int main(int argc, char * argv[]) {
|
||||||
}
|
}
|
||||||
conf.activate();
|
conf.activate();
|
||||||
if (mistOut::listenMode()){
|
if (mistOut::listenMode()){
|
||||||
|
{
|
||||||
|
struct sigaction new_action;
|
||||||
|
new_action.sa_sigaction = handleUSR1;
|
||||||
|
sigemptyset(&new_action.sa_mask);
|
||||||
|
new_action.sa_flags = 0;
|
||||||
|
sigaction(SIGUSR1, &new_action, NULL);
|
||||||
|
}
|
||||||
mistOut::listener(conf, spawnForked);
|
mistOut::listener(conf, spawnForked);
|
||||||
|
if (conf.is_restarting && Socket::checkTrueSocket(0)){
|
||||||
|
INFO_MSG("Reloading input while re-using server socket");
|
||||||
|
execvp(argv[0], argv);
|
||||||
|
FAIL_MSG("Error reloading: %s", strerror(errno));
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
Socket::Connection S(fileno(stdout),fileno(stdin) );
|
Socket::Connection S(fileno(stdout),fileno(stdin) );
|
||||||
mistOut tmp(S);
|
mistOut tmp(S);
|
||||||
|
|
Loading…
Add table
Reference in a new issue