Remove SIGCHLD signal handler

The purpose is to make child_wait() reliable. The handler is meant for
the notify main thread, but signal handlers are shared by all threads.
In the calcurse main thread and the periodic save thread (hooks) the
handler and child_wait() will compete (if the signal handler kicks in
first, the waitpid() call in child_wait() will fail with errno ECHILD).

All child processes in the main thread, the notify thread, the periodic
save thread and the notify demon are explicitly waited for.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
Lars Henriksen 2020-07-14 09:07:00 +02:00 committed by Lukas Fleischer
parent 41e1a89aa7
commit f743eab5ac
4 changed files with 17 additions and 19 deletions

View File

@ -34,7 +34,7 @@
*
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <paths.h>
@ -143,8 +143,7 @@ static unsigned daemonize(int status)
|| !sigs_set_hdlr(SIGTERM, dmon_sigs_hdlr)
|| !sigs_set_hdlr(SIGALRM, dmon_sigs_hdlr)
|| !sigs_set_hdlr(SIGQUIT, dmon_sigs_hdlr)
|| !sigs_set_hdlr(SIGUSR1, dmon_sigs_hdlr)
|| !sigs_set_hdlr(SIGCHLD, SIG_IGN))
|| !sigs_set_hdlr(SIGUSR1, dmon_sigs_hdlr))
return 0;
return 1;
@ -203,6 +202,9 @@ void dmon_start(int parent_exit_status)
DMON_SLEEP_TIME);
psleep(DMON_SLEEP_TIME);
DMON_LOG(_("awakened at %s\n"), nowstr());
/* Reap the user-defined notifications. */
while (waitpid(0, NULL, WNOHANG) > 0)
;
}
}

View File

@ -34,6 +34,7 @@
*
*/
#include <sys/wait.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
@ -358,6 +359,9 @@ static void *notify_main_thread(void *arg)
pthread_mutex_unlock(&notify.mutex);
notify_update_bar();
psleep(thread_sleep);
/* Reap the user-defined notifications. */
while (waitpid(0, NULL, WNOHANG) > 0)
;
elapse += thread_sleep;
if (elapse >= check_app) {
elapse = 0;

View File

@ -68,27 +68,18 @@
/*
* General signal handling routine.
* Catch return values from children (user-defined notification commands).
* This is needed to avoid zombie processes running on system.
* Also catch CTRL-C (SIGINT), and SIGWINCH to resize screen automatically.
* Catch SIGWINCH to resize screen automatically.
*/
static void generic_hdlr(int sig)
{
switch (sig) {
case SIGCHLD:
while (waitpid(WAIT_MYPGRP, NULL, WNOHANG) > 0) ;
break;
case SIGWINCH:
resize = 1;
clearok(curscr, TRUE);
ungetch(KEY_RESIZE);
break;
case SIGTERM:
if (unlink(path_cpid) != 0) {
EXIT(_("Could not remove calcurse lock file: %s\n"),
strerror(errno));
}
exit(EXIT_SUCCESS);
exit_calcurse(EXIT_SUCCESS);
break;
case SIGUSR1:
want_reload = 1;
@ -117,12 +108,11 @@ unsigned sigs_set_hdlr(int sig, void (*handler) (int))
/* Signal handling init. */
void sigs_init()
{
if (!sigs_set_hdlr(SIGCHLD, generic_hdlr)
|| !sigs_set_hdlr(SIGWINCH, generic_hdlr)
if (!sigs_set_hdlr(SIGWINCH, generic_hdlr)
|| !sigs_set_hdlr(SIGTERM, generic_hdlr)
|| !sigs_set_hdlr(SIGUSR1, generic_hdlr)
|| !sigs_set_hdlr(SIGINT, SIG_IGN))
exit_calcurse(1);
exit_calcurse(EXIT_FAILURE);
}
/* Ignore SIGWINCH and SIGTERM signals. */

View File

@ -1425,8 +1425,10 @@ int child_wait(int *pfdin, int *pfdout, int pid)
if (pfdout)
close(*pfdout);
waitpid(pid, &stat, 0);
return stat;
if (waitpid(pid, &stat, 0) == pid)
return stat;
else
return -1;
}
/* Display "Press any key to continue..." and wait for a key press. */