[CRIU] [PATCH 5/7] crtools: dump pending signals

Pavel Emelyanov xemul at parallels.com
Tue Dec 4 06:08:23 EST 2012


On 12/04/2012 01:50 PM, Andrey Vagin wrote:
> signalfd is used for received pending signals, then all signal
> are sent back and saved in a image.
> 
> Only shared signals are restored by now
> 
> Signed-off-by: Andrey Vagin <avagin at openvz.org>
> ---
>  cr-dump.c                  |  6 ++++
>  include/parasite-syscall.h |  1 +
>  include/parasite.h         |  1 +
>  parasite-syscall.c         | 17 +++++++++++
>  pie/parasite.c             | 70 ++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 95 insertions(+)
> 
> diff --git a/cr-dump.c b/cr-dump.c
> index 141caca..f0f31a2 100644
> --- a/cr-dump.c
> +++ b/cr-dump.c
> @@ -1568,6 +1568,12 @@ static int dump_one_task(struct pstree_item *item)
>  		goto err_cure;
>  	}
>  
> +	ret = parasite_dump_signal_seized(parasite_ctl, cr_fdset);
> +	if (ret) {
> +		pr_err("Can't dump pending signals (pid: %d)\n", pid);
> +		goto err_cure;
> +	}
> +
>  	ret = parasite_dump_sigacts_seized(parasite_ctl, cr_fdset);
>  	if (ret) {
>  		pr_err("Can't dump sigactions (pid: %d) with parasite\n", pid);
> diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
> index f4586ef..d547be5 100644
> --- a/include/parasite-syscall.h
> +++ b/include/parasite-syscall.h
> @@ -27,6 +27,7 @@ struct list_head;
>  
>  extern int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_fdset);
>  extern int parasite_dump_itimers_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_fdset);
> +extern int parasite_dump_signal_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_fdset);
>  
>  struct parasite_dump_misc;
>  extern int parasite_dump_misc_seized(struct parasite_ctl *ctl, struct parasite_dump_misc *misc);
> diff --git a/include/parasite.h b/include/parasite.h
> index 3a586fc..5836089 100644
> --- a/include/parasite.h
> +++ b/include/parasite.h
> @@ -36,6 +36,7 @@ enum {
>  	PARASITE_CMD_DRAIN_FDS,
>  	PARASITE_CMD_GET_PROC_FD,
>  	PARASITE_CMD_DUMP_TTY,
> +	PARASITE_CMD_DUMP_SIGNAL,
>  
>  	PARASITE_CMD_MAX,
>  };
> diff --git a/parasite-syscall.c b/parasite-syscall.c
> index 708b1b9..efbbe1c 100644
> --- a/parasite-syscall.c
> +++ b/parasite-syscall.c
> @@ -434,6 +434,23 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, pid_t pid,
>  	return ret;
>  }
>  
> +int parasite_dump_signal_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_fdset)
> +{
> +	int ret, fd;
> +
> +	fd = fdset_fd(cr_fdset, CR_FD_SIGNAL);
> +
> +	ret = parasite_send_fd(ctl, fd);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = parasite_execute(PARASITE_CMD_DUMP_SIGNAL, ctl);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
>  int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_fdset)
>  {
>  	struct parasite_dump_sa_args *args;
> diff --git a/pie/parasite.c b/pie/parasite.c
> index d9e2a1d..901919d 100644
> --- a/pie/parasite.c
> +++ b/pie/parasite.c
> @@ -7,6 +7,7 @@
>  #include <sys/ioctl.h>
>  
>  #include "syscall.h"
> +#include "signalfd.h"
>  #include "parasite.h"
>  #include "log.h"
>  
> @@ -131,6 +132,73 @@ static int sys_write_safe(int fd, void *buf, int size)
>  	return 0;
>  }
>  
> +#define SIGINFO_BUF_SIZE PAGE_SIZE
> +static int dump_signal()
> +{
> +	int ifd, fd, ret, i, size, exit_code = -1;
> +	k_rtsigset_t mask;
> +	siginfo_t *infos;
> +
> +	ksigfillset(&mask);
> +
> +	infos = brk_alloc(SIGINFO_BUF_SIZE);
> +	if (infos == NULL)
> +		return -1;
> +
> +	fd = sys_signalfd(-1, &mask, sizeof(rt_sigset_t),
> +			SFD_RAW | SFD_GROUP | O_NONBLOCK);

You should check that SFD_RAW and others are not supported and don't fail
the dump to let crtools work somehow on non-patched kernels.

> +	if (fd < 0) {
> +		pr_perror("signalfd returned %d\n", fd);
> +		goto free;
> +	}
> +
> +	size = sys_read(fd, infos, SIGINFO_BUF_SIZE);
> +	ret = sys_read(fd, infos, sizeof(siginfo_t));
> +	sys_close(fd);
> +
> +	if (size == -EAGAIN) {
> +		exit_code = 0;
> +		goto free;
> +	}
> +
> +	if (size <= 0) {
> +		pr_err("read() returned %d\n", size);
> +		goto free;
> +	}
> +
> +	if (ret > 0) {
> +		pr_err("BUG: Too many pending signals\n");
> +		goto free;
> +	}
> +
> +	for (i = 0; i < size / sizeof(siginfo_t); i++) {
> +		pr_debug("Dump siginfo for %d %x\n",
> +				infos[i].si_signo, infos[i].si_code);
> +		ret = sys_rt_sigqueueinfo(sys_gettid(),
> +						infos[i].si_signo, infos + i);
> +		if (ret < 0) {
> +			pr_err("rt_sigqueueinfo() failed with code %d", ret);
> +			return -1;
> +		}
> +	}
> +
> +	ifd = recv_fd(tsock);
> +	if (ifd < 0)
> +		goto free;
> +
> +	ret = sys_write(ifd, infos, size);
> +	sys_close(ifd);
> +	if (ret != size) {
> +		pr_err("send() returned %d\n", ret);
> +		goto free;
> +	}
> +
> +	exit_code = 0;
> +free:
> +	brk_free(SIGINFO_BUF_SIZE);
> +	return exit_code;
> +}
> +
>  /*
>   * This is the main page dumping routine, it's executed
>   * inside a victim process space.
> @@ -635,6 +703,8 @@ int __used parasite_service(unsigned int cmd, void *args)
>  		return parasite_get_proc_fd();
>  	case PARASITE_CMD_DUMP_TTY:
>  		return parasite_dump_tty(args);
> +	case PARASITE_CMD_DUMP_SIGNAL:
> +		return dump_signal();
>  	}
>  
>  	pr_err("Unknown command to parasite\n");
> 




More information about the CRIU mailing list