[CRIU] [PATCH] service: SIGCHLD handler
Andrew Vagin
avagin at parallels.com
Wed Oct 30 04:40:37 PDT 2013
On Wed, Oct 30, 2013 at 03:35:12AM +0400, Ruslan Kuprieiev wrote:
> Hi!
>
> Now we're ignoring SIGCHLD from forked children.
> This patch provides SIGCHLD handler, that will wait for child and write some
> information about it's exit status to logfile.
>
> P.S. This is my first signal handler, so please take a good look at this patch.
>
> Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
> ---
> cr-service.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 65 insertions(+), 3 deletions(-)
>
> diff --git a/cr-service.c b/cr-service.c
> index a79ebc7..f966036 100644
> --- a/cr-service.c
> +++ b/cr-service.c
> @@ -19,6 +19,8 @@
> #include "pstree.h"
> #include "cr-service.h"
>
> +#define MAX_WORKERS 16
> +
> unsigned int service_sk_ino = -1;
>
> static int recv_criu_msg(int socket_fd, CriuReq **msg)
> @@ -253,6 +255,46 @@ err:
> return -1;
> }
>
> +static void reap_worker(int signo)
> +{
> + int saved_errno;
> + int status;
> + pid_t pid;
> +
> + (void)signo;
for what?
> +
> + saved_errno = errno;
I have never seen that someone save errno in a signal handler,
but it really has sense.
> +
> + errno = 0;
for what?
> + pid = waitpid(-1, &status, WNOHANG|WUNTRACED|WCONTINUED);
signal(7)
1. Multiple instances of real-time signals can be queued. By
contrast, if multiple instances of a standard signal are
delivered while that signal is currently blocked, then only one
instance is queued.
SIGCHLD is a standard signal, so sigchld handler can be executed once,
even if more than one worker completed.
> +
> + if (pid <= 0) {
> + errno = saved_errno;
> + return;
> + }
> +
> + if (WIFEXITED(status))
> + pr_info("Worker(pid %d) exited with %d\n",
> + pid, WEXITSTATUS(status));
> +
> + else if (WIFSIGNALED(status)) {
> + pr_info("Worker(pid %d) ", pid);
> +#ifdef WCOREDUMP
> + if (WCOREDUMP(status))
> + pr_info("prodused a core dump and ");
> +#endif
> + pr_info("was killed by %d\n", WTERMSIG(status));
> +
> + } else if (WIFSTOPPED(status))
> + pr_info("Worker(pid %d) was stopped by %d\n",
> + pid, WSTOPSIG(status));
Do we get SIGCHLD if a task was stopped?
> +
> + else if (WIFCONTINUED(status))
> + pr_info("Worker(pid %d) was continued\n", pid);
> +
> + errno = saved_errno;
> +}
> +
> int cr_service(bool daemon_mode)
> {
> int server_fd = -1;
> @@ -264,6 +306,9 @@ int cr_service(bool daemon_mode)
> socklen_t server_addr_len;
> socklen_t client_addr_len;
>
> + struct sigaction setup_action;
> + sigset_t block_mask;
> +
> server_fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
> if (server_fd == -1) {
> pr_perror("Can't initialize service socket.");
> @@ -299,7 +344,7 @@ int cr_service(bool daemon_mode)
> goto err;
> }
>
> - if (listen(server_fd, 16) == -1) {
> + if (listen(server_fd, MAX_WORKERS) == -1) {
> pr_perror("Can't listen for socket connections.");
> goto err;
> }
> @@ -323,16 +368,31 @@ int cr_service(bool daemon_mode)
> }
> }
>
> - /* FIXME Do not ignore children's return values */
> - signal(SIGCHLD, SIG_IGN);
> + /* Set SIGCHLD handler */
> + sigemptyset(&block_mask);
> +
> + sigaddset(&block_mask, SIGCHLD);
> +
> + /* FIXME May need to block some other signals too */
I think we don't need to block only SIGCHLD.
> + sigaddset(&block_mask, SIGINT);
> + sigaddset(&block_mask, SIGQUIT);
> +
> + setup_action.sa_handler = reap_worker;
> + setup_action.sa_mask = block_mask;
> + setup_action.sa_flags = 0;
Pls, add SA_RESTART or you must handle EINTR for each syscall
> +
> + sigaction(SIGCHLD, &setup_action, NULL);
>
> while (1) {
> int sk;
>
> pr_info("Waiting for connection...\n");
>
> + errno = 0;
It's not required.
> sk = accept(server_fd, &client_addr, &client_addr_len);
> if (sk == -1) {
> + if (errno == EINTR)
> + continue;
> pr_perror("Can't accept connection.");
> goto err;
> }
> @@ -340,6 +400,8 @@ int cr_service(bool daemon_mode)
> pr_info("Connected.\n");
> child_pid = fork();
> if (child_pid == 0) {
> + /* Set default SIGCHLD handler back */
> + signal(SIGCHLD, SIG_DFL);
warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
> int ret;
>
> close(server_fd);
> --
> 1.8.1.2
>
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
More information about the CRIU
mailing list