From e085ee53de0540a14305b4234248f94f2b9ee34d Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Thu, 15 Apr 2021 15:43:55 +0200 Subject: [PATCH 1/2] restore original procmask for child process --- procServ.cc | 2 +- procServ.h | 2 +- processClass.h | 4 ++-- processFactory.cc | 7 ++++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/procServ.cc b/procServ.cc index 750a6c1..5bcb7fa 100644 --- a/procServ.cc +++ b/procServ.cc @@ -657,7 +657,7 @@ int main(int argc,char * argv[]) PRINTF("Option oneshot is set... exiting\n"); shutdownServer = true; } else { - npi= processFactory(childExec, childArgv); + npi= processFactory(childExec, childArgv, &sigset_pselect); if (npi) AddConnection(npi); if (firstRun) { firstRun = false; diff --git a/procServ.h b/procServ.h index 0dcb381..3575367 100644 --- a/procServ.h +++ b/procServ.h @@ -87,7 +87,7 @@ void DeleteConnection(connectionItem *ci); // constructors are public: // processFactory creates the process that we are managing -connectionItem * processFactory(char *exe, char *argv[]); +connectionItem * processFactory(char *exe, char *argv[], sigset_t *sigset); bool processFactoryNeedsRestart(); // Call to test status of the server process void processFactorySendSignal(int signal); diff --git a/processClass.h b/processClass.h index 0beea2c..cf5d645 100644 --- a/processClass.h +++ b/processClass.h @@ -15,11 +15,11 @@ class processClass : public connectionItem { -friend connectionItem * processFactory(char *exe, char *argv[]); +friend connectionItem * processFactory(char *exe, char *argv[], sigset_t *sigset); friend bool processFactoryNeedsRestart(); friend void processFactorySendSignal(int signal); public: - processClass(char *exe, char *argv[]); + processClass(char *exe, char *argv[], sigset_t *sigset); void readFromFd(void); int Send(const char *,int); void markDeadIfChildIs(pid_t pid) { if (pid==_pid) _markedForDeletion=true; } diff --git a/processFactory.cc b/processFactory.cc index f86e4dd..1126b88 100644 --- a/processFactory.cc +++ b/processFactory.cc @@ -55,7 +55,7 @@ bool processFactoryNeedsRestart() return true; } -connectionItem * processFactory(char *exe, char *argv[]) +connectionItem * processFactory(char *exe, char *argv[], sigset_t *sigset) { const size_t BUFLEN = 512; char buf[BUFLEN]; @@ -71,7 +71,7 @@ connectionItem * processFactory(char *exe, char *argv[]) SendToAll( buf, strlen(buf), 0 ); } - connectionItem *ci = new processClass(exe, argv); + connectionItem *ci = new processClass(exe, argv, sigset); PRINTF("Created new child connection (processClass %p)\n", ci); return ci; } @@ -126,7 +126,7 @@ processClass::~processClass() // parent: sets the minimum time for the next restart // child: sets the coresize, becomes a process group leader, // and does an execvp() with the command -processClass::processClass(char *exe, char *argv[]) +processClass::processClass(char *exe, char *argv[], sigset_t *sigset) { _runningItem=this; struct rlimit corelimit; @@ -208,6 +208,7 @@ processClass::processClass(char *exe, char *argv[]) corelimit.rlim_cur = coreSize; setrlimit( RLIMIT_CORE, &corelimit ); } + sigprocmask(SIG_SETMASK, sigset, NULL); if ( chDir && chdir( chDir ) ) { fprintf( stderr, "%s: child could not chdir to %s, %s\n", procservName, chDir, strerror(errno) ); From 7484be566c9df133582f5b80bf83fd2b8b9b7e8b Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Thu, 15 Apr 2021 18:37:16 +0200 Subject: [PATCH 2/2] replace ignoring signals with blocking signals for easy restore in clild process --- procServ.cc | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/procServ.cc b/procServ.cc index 5bcb7fa..7e65f7c 100644 --- a/procServ.cc +++ b/procServ.cc @@ -475,38 +475,44 @@ int main(int argc,char * argv[]) memset(&sig, 0, sizeof(sig)); PRINTF("Installing signal handlers\n"); - + // SIGPIPE, SIGTERM and SIGHUP will be handled in the main loop // with the assistance of pselect. This means that we have them // blocked outside of pselect call, but unblocked atomically // within pselect. Each time pselect returns, we safely check if // any of the signals were received. - - // Block the signals that we bill be handling in the main loop. + + // Block the signals that we will be handling in the main loop + // and re-enable them during pselect. // At the same time, retrieve the original signal mask before - // blocking, to be passed to pselect. + // blocking, to be passed to the child processes. + sigset_t sigset_block; + sigset_t sigset_child; sigset_t sigset_pselect; sigemptyset(&sigset_block); sigaddset(&sigset_block, SIGPIPE); sigaddset(&sigset_block, SIGTERM); sigaddset(&sigset_block, SIGHUP); - sigprocmask(SIG_BLOCK, &sigset_block, &sigset_pselect); - + sigaddset(&sigset_block, SIGXFSZ); + if (inFgMode) { + sigaddset(&sigset_block, SIGINT); + sigaddset(&sigset_block, SIGQUIT); + } + sigprocmask(SIG_BLOCK, &sigset_block, &sigset_child); + + // enable SIGPIPE, SIGTERM and SIGHUP during pselect + sigprocmask(0, NULL, &sigset_pselect); + sigdelset(&sigset_pselect, SIGTERM); + sigdelset(&sigset_pselect, SIGHUP); + sigdelset(&sigset_pselect, SIGPIPE); + sig.sa_handler = &OnSigPipe; // sigaction() needed for Solaris sigaction(SIGPIPE, &sig, NULL); sig.sa_handler = &OnSigTerm; sigaction(SIGTERM, &sig, NULL); sig.sa_handler = &OnSigHup; sigaction(SIGHUP, &sig, NULL); - sig.sa_handler = SIG_IGN; - sigaction(SIGXFSZ, &sig, NULL); - if (inFgMode) { - sig.sa_handler = SIG_IGN; - sigaction(SIGINT, &sig, NULL); - sig.sa_handler = SIG_IGN; - sigaction(SIGQUIT, &sig, NULL); - } // Make an accept item to listen for control connections PRINTF("Creating control listener\n"); @@ -657,7 +663,7 @@ int main(int argc,char * argv[]) PRINTF("Option oneshot is set... exiting\n"); shutdownServer = true; } else { - npi= processFactory(childExec, childArgv, &sigset_pselect); + npi= processFactory(childExec, childArgv, &sigset_child); if (npi) AddConnection(npi); if (firstRun) { firstRun = false;