[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