[CRIU] [PATCH 5/7] crtools: dump pending signals
Andrey Vagin
avagin at openvz.org
Tue Dec 4 04:50:29 EST 2012
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);
+ 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");
--
1.7.11.7
More information about the CRIU
mailing list