[CRIU] [PATCH 08/14] crtools: dump pending signals (v2)

Andrey Vagin avagin at openvz.org
Thu Jan 17 09:38:32 EST 2013


signalfd is used for received pending signals, then all signal
are sent back and saved in a image.

v2: rework according with the new kernel interface

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-dump.c                  | 28 +++++++++++++++++++++++++---
 include/parasite-syscall.h |  1 +
 include/parasite.h         |  7 +++++++
 parasite-syscall.c         | 31 +++++++++++++++++++++++++++++++
 pie/parasite.c             | 31 +++++++++++++++++++++++++++++++
 5 files changed, 95 insertions(+), 3 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index 4a1e9e9..d90df84 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1279,6 +1279,19 @@ err:
 
 static struct proc_pid_stat pps_buf;
 
+static int dump_signals(struct parasite_ctl *ctl, struct pid *pid)
+{
+	int fd, ret;
+
+	fd = open_image(CR_FD_PSIGNAL, O_DUMP, pid->virt);
+	if (fd < 0)
+		return -1;
+	ret = parasite_dump_signal_seized(pid->real, ctl, fd, 0);
+	close(fd);
+
+	return ret;
+}
+
 static int dump_task_threads(struct parasite_ctl *parasite_ctl,
 			     const struct pstree_item *item)
 {
@@ -1286,12 +1299,14 @@ static int dump_task_threads(struct parasite_ctl *parasite_ctl,
 
 	for (i = 0; i < item->nr_threads; i++) {
 		/* Leader is already dumped */
-		if (item->pid.real == item->threads[i].real) {
+		if (item->pid.real == item->threads[i].real)
 			item->threads[i].virt = item->pid.virt;
-			continue;
+		else {
+			if (dump_task_thread(parasite_ctl, &item->threads[i]))
+				return -1;
 		}
 
-		if (dump_task_thread(parasite_ctl, &item->threads[i]))
+		if (dump_signals(parasite_ctl, &item->threads[i]))
 			return -1;
 	}
 
@@ -1477,6 +1492,13 @@ static int dump_one_task(struct pstree_item *item)
 		goto err_cure;
 	}
 
+	ret = parasite_dump_signal_seized(pid, parasite_ctl,
+					fdset_fd(cr_fdset, CR_FD_SIGNAL), 1);
+	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 0c222fb..20f2b32 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(pid_t tid, struct parasite_ctl *ctl, int fd, bool group);
 
 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 4397873..3da3d33 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,
 };
@@ -54,6 +55,12 @@ struct parasite_log_args {
 	int log_level;
 };
 
+struct parasite_dump_signal_args {
+	bool group;
+	int nr;
+	siginfo_t siginfos[PARASITE_ARG_SIZE / sizeof(siginfo_t) - 1];
+};
+
 struct parasite_dump_pages_args {
 	VmaEntry		vma_entry;
 	unsigned long		nrpages_dumped;	/* how many pages are dumped */
diff --git a/parasite-syscall.c b/parasite-syscall.c
index c3510d8..92e9ceb 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -10,6 +10,7 @@
 #include "protobuf/itimer.pb-c.h"
 #include "protobuf/creds.pb-c.h"
 #include "protobuf/core.pb-c.h"
+#include "protobuf/siginfo.pb-c.h"
 
 #include "syscall.h"
 #include "ptrace.h"
@@ -369,6 +370,36 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, struct pid *tid,
 	return ret;
 }
 
+int parasite_dump_signal_seized(pid_t tid, struct parasite_ctl *ctl, int fd, bool group)
+{
+	struct parasite_dump_signal_args *args;
+	int size, ret, i;
+
+	args = parasite_args(ctl, struct parasite_dump_signal_args);
+	args->nr = 0;
+	args->group = group;
+
+	ret = 0;
+	while (1) {
+		size = parasite_execute_by_pid(PARASITE_CMD_DUMP_SIGNAL, ctl, tid);
+		if (size <= 0)
+			break;
+
+		for (i = 0; i < size / sizeof(siginfo_t); i++) {
+			SiginfoEntry sie = SIGINFO_ENTRY__INIT;
+			sie.siginfo.len = sizeof(siginfo_t);
+			sie.siginfo.data = (void *)(args->siginfos + i);
+
+			ret = pb_write_one(fd, &sie, PB_SIGINFO);
+			if (ret < 0)
+				break;
+			args->nr++;
+		}
+	}
+
+	return ret;
+}
+
 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 3e444ea..351df04 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"
 
@@ -129,6 +130,34 @@ static int sys_write_safe(int fd, void *buf, int size)
 	return 0;
 }
 
+static int dump_signals(struct parasite_dump_signal_args *arg)
+{
+	int fd, ret = -1;
+	off_t off;
+	k_rtsigset_t mask;
+
+	off = arg->nr;
+
+	if (arg->group)
+		off += SIGNALFD_SHARED_OFFSET;
+	else
+		off += SIGNALFD_PRIVATE_OFFSET;
+
+	ksigfillset(&mask);
+
+	fd = sys_signalfd(-1, &mask, sizeof(rt_sigset_t),
+			SFD_RAW | O_NONBLOCK);
+	if (fd < 0) {
+		pr_perror("signalfd returned %d\n", fd);
+		return fd;
+	}
+
+	ret = sys_pread(fd, (void *) arg->siginfos, sizeof(arg->siginfos), off);
+	sys_close(fd);
+
+	return ret;
+}
+
 /*
  * This is the main page dumping routine, it's executed
  * inside a victim process space.
@@ -637,6 +666,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_signals(args);
 	}
 
 	pr_err("Unknown command to parasite\n");
-- 
1.7.11.7



More information about the CRIU mailing list