From: Bartlomiej Grzelewski Date: Wed, 17 Jul 2013 14:46:34 +0000 (+0200) Subject: Clean up after SIGTERM. X-Git-Tag: accepted/tizen/generic/20140307.163312~88 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4373766ae94f58cdfada5560455249a67af681dd;p=platform%2Fcore%2Fsecurity%2Fsecurity-server.git Clean up after SIGTERM. [Issue#] N/A [Bug] N/A [Cause] Lack of SIGTERM support. [Problem] N/A [Solution] Add support for SIGTERM signal. [Verification] Use "systemctl restart security-server.service" command. Security server should be killed and restarted. Change-Id: Ic41957bf3aaee60afb98cae6de841a057f3ad49a --- diff --git a/src/server/security-server-main.c b/src/server/security-server-main.c index 81797a6..dcbf484 100644 --- a/src/server/security-server-main.c +++ b/src/server/security-server-main.c @@ -1368,14 +1368,21 @@ int main(int argc, char *argv[]) (void)argc; (void)argv; + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGTERM); + sigaddset(&mask, SIGPIPE); + if (-1 == pthread_sigmask(SIG_BLOCK, &mask, NULL)) { + SEC_SVR_ERR("Error in pthread_sigmask"); + } + if (0 != (res = pthread_create(&main_thread, NULL, security_server_main_thread, NULL))) { SEC_SVR_ERR("Error: Server: Cannot create main security server thread: %s", strerror(res)); return -1; } server2(); - - pthread_exit(NULL); + exit(0); return 0; } diff --git a/src/server2/main/generic-socket-manager.h b/src/server2/main/generic-socket-manager.h index f9d11f4..a0244b4 100644 --- a/src/server2/main/generic-socket-manager.h +++ b/src/server2/main/generic-socket-manager.h @@ -93,6 +93,8 @@ struct GenericSocketService { virtual void Event(const ReadEvent &event) = 0; virtual void Event(const CloseEvent &event) = 0; virtual void Event(const ErrorEvent &event) = 0; + + GenericSocketService() : m_serviceManager(NULL) {} virtual ~GenericSocketService(){} protected: GenericSocketManager *m_serviceManager; diff --git a/src/server2/main/socket-manager.cpp b/src/server2/main/socket-manager.cpp index 1f6c0d1..481f7ae 100644 --- a/src/server2/main/socket-manager.cpp +++ b/src/server2/main/socket-manager.cpp @@ -22,7 +22,11 @@ * @brief Implementation of SocketManager. */ +#include + +#include #include +#include #include #include #include @@ -61,6 +65,48 @@ struct DummyService : public GenericSocketService { void Event(const ErrorEvent &event) { (void)event; } }; +struct SignalService : public GenericSocketService { + int GetDescriptor() { + LogInfo("set up"); + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGTERM); + if (-1 == pthread_sigmask(SIG_BLOCK, &mask, NULL)) + return -1; + return signalfd(-1, &mask, 0); + } + + ServiceDescriptionVector GetServiceDescription() { + return ServiceDescriptionVector(); + } + + void Event(const AcceptEvent &event) { (void)event; } // not supported + void Event(const WriteEvent &event) { (void)event; } // not supported + void Event(const CloseEvent &event) { (void)event; } // not supported + void Event(const ErrorEvent &event) { (void)event; } // not supported + + void Event(const ReadEvent &event) { + LogDebug("Get signal information"); + + if(sizeof(struct signalfd_siginfo) != event.rawBuffer.size()) { + LogError("Wrong size of signalfd_siginfo struct. Expected: " + << sizeof(signalfd_siginfo) << " Get: " + << event.rawBuffer.size()); + return; + } + + signalfd_siginfo *siginfo = (signalfd_siginfo*)(&(event.rawBuffer[0])); + + if (siginfo->ssi_signo == SIGTERM) { + LogInfo("Got signal: SIGTERM"); + static_cast(m_serviceManager)->MainLoopStop(); + return; + } + + LogInfo("This should not happend. Got signal: " << siginfo->ssi_signo); + } +}; + SocketManager::SocketDescription& SocketManager::CreateDefaultReadSocketDescription(int sock, bool timeout) { @@ -110,10 +156,41 @@ SocketManager::SocketManager() sigemptyset(&set); sigaddset(&set, SIGPIPE); pthread_sigmask(SIG_BLOCK, &set, NULL); + + // add support for TERM signal (passed from systemd) + auto *signalService = new SignalService; + int filefd = signalService->GetDescriptor(); + if (-1 == filefd) { + LogError("Error in SignalService.GetDescriptor()"); + delete signalService; + } else { + auto &desc2 = CreateDefaultReadSocketDescription(filefd, false); + desc2.service = signalService; + LogInfo("SignalService mounted on " << filefd << " descriptor"); + } } SocketManager::~SocketManager() { - // TODO clean up all services! + std::set serviceMap; + + // Find all services. Set is used to remove duplicates. + // In this implementation, services are not able to react in any way. + for (size_t i=0; i < m_socketDescriptionVector.size(); ++i) + if (m_socketDescriptionVector[i].isOpen) + serviceMap.insert(m_socketDescriptionVector[i].service); + + // Time to destroy all services. + for(auto it = serviceMap.begin(); it != serviceMap.end(); ++it) { + LogDebug("delete " << (void*)(*it)); + delete *it; + } + + for (size_t i = 0; i < m_socketDescriptionVector.size(); ++i) + if (m_socketDescriptionVector[i].isOpen) + close(i); + + // All socket except one were closed. Now pipe input must be closed. + close(m_notifyMe[1]); } void SocketManager::ReadyForAccept(int sock) { @@ -320,6 +397,12 @@ void SocketManager::MainLoop() { } } +void SocketManager::MainLoopStop() +{ + m_working = false; + NotifyMe(); +} + int SocketManager::GetSocketFromSystemD( const GenericSocketService::ServiceDescription &desc) { @@ -341,7 +424,7 @@ int SocketManager::GetSocketFromSystemD( desc.serviceHandlerPath.c_str(), 0)) { LogInfo("Useable socket " << desc.serviceHandlerPath << - " was passed by SystemD"); + " was passed by SystemD under descriptor " << fd); return fd; } } diff --git a/src/server2/main/socket-manager.h b/src/server2/main/socket-manager.h index 12203fe..0983a3f 100644 --- a/src/server2/main/socket-manager.h +++ b/src/server2/main/socket-manager.h @@ -48,6 +48,7 @@ public: SocketManager(); virtual ~SocketManager(); virtual void MainLoop(); + virtual void MainLoopStop(); virtual void RegisterSocketService(GenericSocketService *service); virtual void Close(ConnectionID connectionID);