[PATCH 17/35] monitor: handle SIGCHLD for terminated child processes

Sagi Grimberg sagi at grimberg.me
Thu Jan 28 20:54:32 EST 2021


No commit message?
> Signed-off-by: Martin Wilck <mwilck at suse.com>
> ---
>   monitor.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
>   1 file changed, 48 insertions(+), 2 deletions(-)
> 
> diff --git a/monitor.c b/monitor.c
> index 9375a14..8db40e6 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -26,6 +26,8 @@
>   #include <limits.h>
>   #include <syslog.h>
>   #include <sys/stat.h>
> +#include <sys/types.h>
> +#include <sys/wait.h>
>   #include <sys/epoll.h>
>   
>   #include "common.h"
> @@ -100,6 +102,13 @@ static void monitor_int_handler(int sig)
>   	must_exit = 1;
>   }
>   
> +static sig_atomic_t got_sigchld;
> +
> +static void monitor_chld_handler(int sig)
> +{
> +	got_sigchld = 1;
> +}
> +
>   static sigset_t orig_sigmask;
>   
>   static int monitor_init_signals(void)
> @@ -118,6 +127,9 @@ static int monitor_init_signals(void)
>   		return -errno;
>   	if (sigaction(SIGINT, &sa, NULL) == -1)
>   		return -errno;
> +	sa.sa_handler = monitor_chld_handler;
> +	if (sigaction(SIGCHLD, &sa, NULL) == -1)
> +		return -errno;
>   	return 0;
>   }
>   
> @@ -336,6 +348,34 @@ static void monitor_handle_uevents(struct udev_monitor *monitor)
>   	}
>   }
>   
> +static void handle_sigchld(void)
> +{
> +	while (true) {
> +		int wstatus;
> +		pid_t pid;
> +
> +		pid = waitpid(-1, &wstatus, WNOHANG);
> +		switch(pid) {
> +		case -1:
> +			if (errno != ECHILD)
> +				log(LOG_ERR, "error in waitpid: %m\n");
> +			return;
> +		case 0:
> +			return;
> +		default:
> +			break;
> +		}
> +		if (!WIFEXITED(wstatus))
> +			log(LOG_WARNING, "child %ld didn't exit normally\n",
> +			    (long)pid);
> +		else if (WEXITSTATUS(wstatus) != 0)
> +			log(LOG_NOTICE, "child %ld exited with status \"%s\"\n",
> +			    (long)pid, strerror(WEXITSTATUS(wstatus)));
> +		else
> +			log(LOG_DEBUG, "child %ld exited normally\n", (long)pid);
> +	};
> +}
> +
>   #define MAX_EVENTS 1
>   static int monitor_main_loop(struct udev_monitor *monitor)
>   {
> @@ -357,13 +397,19 @@ static int monitor_main_loop(struct udev_monitor *monitor)
>   	sigfillset(&ep_mask);
>   	sigdelset(&ep_mask, SIGTERM);
>   	sigdelset(&ep_mask, SIGINT);
> +	sigdelset(&ep_mask, SIGCHLD);
>   	while (1) {
>   		int rc, i;
>   
>   		rc = epoll_pwait(ep_fd, events, MAX_EVENTS, -1, &ep_mask);
>   		if (rc == -1 && errno == EINTR) {
> -			log(LOG_NOTICE, "monitor: exit signal received\n");
> -			return 0;
> +			if (must_exit) {
> +				log(LOG_NOTICE, "monitor: exit signal received\n");
> +				return 0;
> +			} else if (got_sigchld) {
> +				got_sigchld = 0;
> +				handle_sigchld();
> +			}
>   		} else if (rc == -1) {
>   			log(LOG_ERR, "monitor: epoll_wait: %m\n");
>   			return -errno;
> 



More information about the Linux-nvme mailing list