Exit parent after daemon is initialized. Safer signal handling. Fix #519

This commit is contained in:
Guy McSwain 2022-05-13 10:49:37 -05:00
parent f077c61882
commit eec9367e46
1 changed files with 54 additions and 21 deletions

View File

@ -67,6 +67,9 @@ static uint32_t cfgInternals = PI_DEFAULT_CFG_INTERNALS;
static int updateMaskSet = 0; static int updateMaskSet = 0;
static FILE * errFifo; static FILE * errFifo;
volatile sig_atomic_t hupFlag = 0;
volatile sig_atomic_t termFlag = 0;
volatile sig_atomic_t contFlag = 0;
static uint32_t sockNetAddr[MAX_CONNECT_ADDRESSES]; static uint32_t sockNetAddr[MAX_CONNECT_ADDRESSES];
@ -286,13 +289,15 @@ static void initOpts(int argc, char *argv[])
} }
} }
void terminate(int signum) void terminate()
{ {
/* only registered for SIGHUP/SIGTERM */ /* only registered for SIGHUP/SIGTERM/SIGCONT */
gpioTerminate(); gpioTerminate();
fprintf(errFifo, "SIGHUP/SIGTERM received\n"); if (hupFlag) fprintf(stderr, "SIGHUP received %d times\n", hupFlag);
if (termFlag) fprintf(stderr, "SIGTERM received %d times\n", termFlag);
if (contFlag) fprintf(stderr, "SIGCONT received %d times\n", contFlag);
fflush(NULL); fflush(NULL);
@ -303,6 +308,16 @@ void terminate(int signum)
exit(0); exit(0);
} }
void mySigHandler(int signum)
{
/* Catch multiple signals - ie systemd issues SIGTERM and SIGCONT */
switch (signum)
{
case SIGHUP: hupFlag++; break;
case SIGTERM: termFlag++; break;
case SIGCONT: contFlag++; break;
}
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
@ -313,7 +328,18 @@ int main(int argc, char **argv)
initOpts(argc, argv); initOpts(argc, argv);
if (!foreground) { /* create pipe for error reporting & communicate child init is complete */
unlink(PI_ERRFIFO);
mkfifo(PI_ERRFIFO, 0664);
if (chmod(PI_ERRFIFO, 0664) < 0)
fatal("chmod %s failed (%m)", PI_ERRFIFO);
if (!foreground)
{
/* Fork off the parent process */ /* Fork off the parent process */
pid = fork(); pid = fork();
@ -322,7 +348,16 @@ int main(int argc, char **argv)
/* If we got a good PID, then we can exit the parent process. */ /* If we got a good PID, then we can exit the parent process. */
if (pid > 0) { exit(EXIT_SUCCESS); } if (pid > 0)
{
FILE *fdFifo = fopen(PI_ERRFIFO, "r"); // block until daemon init'ed
if (fdFifo == NULL) {
perror("parent could not open pipe");
exit(EXIT_FAILURE);
}
else exit(EXIT_SUCCESS);
}
/* Change the file mode mask */ /* Change the file mode mask */
@ -370,16 +405,15 @@ int main(int argc, char **argv)
if (gpioInitialise()< 0) fatal("Can't initialise pigpio library"); if (gpioInitialise()< 0) fatal("Can't initialise pigpio library");
/* create pipe for error reporting */ /* open errFifo */
unlink(PI_ERRFIFO); // daemon logs messages to errFifo (normal)
if (getenv("PIGPIO_ENV_LOG_STDERR") == NULL)
errFifo = freopen(PI_ERRFIFO, "w+", stderr);
mkfifo(PI_ERRFIFO, 0664); // daemon logs to stderr
else
if (chmod(PI_ERRFIFO, 0664) < 0) errFifo = fopen(PI_ERRFIFO, "w+");
fatal("chmod %s failed (%m)", PI_ERRFIFO);
errFifo = freopen(PI_ERRFIFO, "w+", stderr);
if (errFifo) if (errFifo)
{ {
@ -388,21 +422,20 @@ int main(int argc, char **argv)
flags = fcntl(fileno(errFifo), F_GETFL, 0); flags = fcntl(fileno(errFifo), F_GETFL, 0);
fcntl(fileno(errFifo), F_SETFL, flags | O_NONBLOCK); fcntl(fileno(errFifo), F_SETFL, flags | O_NONBLOCK);
/* request SIGHUP/SIGTERM from libarary for termination */ /* install handlers for safe exit on SIGHUP/SIGTERM/SIGCONT */
gpioSetSignalFunc(SIGHUP, terminate); gpioSetSignalFunc(SIGHUP, mySigHandler);
gpioSetSignalFunc(SIGTERM, terminate); gpioSetSignalFunc(SIGTERM, mySigHandler);
gpioSetSignalFunc(SIGCONT, mySigHandler); //systemd along w/SIGTERM
/* sleep forever */ /* sleep until signaled */
while (1) while (hupFlag==0 && termFlag==0 && contFlag==0)
{ {
/* cat /dev/pigerr to view daemon errors */
sleep(5); sleep(5);
fflush(errFifo); fflush(errFifo);
} }
terminate();
} }
else else
{ {