[CRIU] [PATCH 06/12] crtools: dump pending signals
Andrey Vagin
avagin at openvz.org
Tue Dec 18 01:36:09 EST 2012
signalfd is used for received pending signals, then all signal
are sent back and saved in a image.
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
cr-dump.c | 30 +++++++++++++++--
include/parasite-syscall.h | 1 +
include/parasite.h | 5 +++
parasite-syscall.c | 41 ++++++++++++++++++++++
pie/parasite.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 158 insertions(+), 3 deletions(-)
diff --git a/cr-dump.c b/cr-dump.c
index 281dc9e..3d0c9e5 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -886,14 +886,15 @@ err:
return NULL;
}
-static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat,
- const struct parasite_dump_misc *misc, const struct parasite_ctl *ctl,
+static int dump_task_core_all(struct pstree_item *item, const struct proc_pid_stat *stat,
+ const struct parasite_dump_misc *misc, struct parasite_ctl *ctl,
const struct cr_fdset *cr_fdset,
struct list_head *vma_area_list)
{
int fd_core = fdset_fd(cr_fdset, CR_FD_CORE);
CoreEntry *core;
int ret = -1;
+ int pid = item->pid.real;
core = core_entry_alloc(1, 1, 1);
if (!core)
@@ -941,6 +942,12 @@ static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat,
if (ret < 0)
goto err_free;
+ fd_core = open_image(CR_FD_PSIGNAL, O_DUMP, item->pid.virt);
+ if (fd_core < 0)
+ goto err_free;
+ ret = parasite_dump_signal_seized(pid, ctl, fd_core, 0);
+ close(fd_core);
+
err_free:
core_entry_free(core);
pr_info("----------------------------------------\n");
@@ -1343,6 +1350,16 @@ static int dump_task_thread(struct parasite_ctl *parasite_ctl, struct pid *tid)
ret = pb_write_one(fd_core, core, PB_CORE);
close(fd_core);
+
+ if (ret)
+ goto err_free;
+
+ fd_core = open_image(CR_FD_PSIGNAL, O_DUMP, tid->virt);
+ if (fd_core < 0)
+ goto err_free;
+ ret = parasite_dump_signal_seized(pid, parasite_ctl, fd_core, 0);
+ close(fd_core);
+
err_free:
core_entry_free(core);
err:
@@ -1567,6 +1584,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);
@@ -1579,7 +1603,7 @@ static int dump_one_task(struct pstree_item *item)
goto err_cure;
}
- ret = dump_task_core_all(pid, &pps_buf, &misc,
+ ret = dump_task_core_all(item, &pps_buf, &misc,
parasite_ctl, cr_fdset, &vma_area_list);
if (ret) {
pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index f4586ef..1551887 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 3a586fc..2ed24f6 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,10 @@ struct parasite_log_args {
int log_level;
};
+struct parasite_dump_signal_args {
+ bool group;
+};
+
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 420dc43..bafc5b2 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -8,6 +8,7 @@
#include "protobuf/sa.pb-c.h"
#include "protobuf/itimer.pb-c.h"
#include "protobuf/creds.pb-c.h"
+#include "protobuf/siginfo.pb-c.h"
#include "syscall.h"
#include "ptrace.h"
@@ -434,6 +435,46 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, pid_t pid,
return ret;
}
+int parasite_dump_signal_seized(pid_t tid, struct parasite_ctl *ctl, int fd, bool group)
+{
+ struct parasite_dump_signal_args *args;
+ siginfo_t *infos;
+ int size, ret, i;
+
+ args = parasite_args(ctl, struct parasite_dump_signal_args);
+ args->group = group;
+
+ ret = parasite_execute_by_pid(PARASITE_CMD_DUMP_SIGNAL, ctl, tid);
+ if (ret < 0)
+ return ret;
+
+ infos = xmalloc(ret);
+ if (infos == NULL)
+ return -1;
+
+ size = read(ctl->tsock, infos, ret);
+ if (size != ret) {
+ pr_perror("Unalbe to read data from parasite %d (expected %d)",
+ size, ret);
+ xfree(infos);
+ return -1;
+ }
+
+ ret = 0;
+ for (i = 0; i < size / sizeof(siginfo_t); i++) {
+ SiginfoEntry sie = SIGINFO_ENTRY__INIT;
+ sie.siginfo.len = sizeof(siginfo_t);
+ sie.siginfo.data = (void *)(infos + i);
+
+ ret = pb_write_one(fd, &sie, PB_SIGINFO);
+ if (ret < 0)
+ break;
+ }
+ xfree(infos);
+
+ 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 d9e2a1d..4a2d644 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,87 @@ static int sys_write_safe(int fd, void *buf, int size)
return 0;
}
+static int dump_signal(struct parasite_dump_signal_args *arg)
+{
+ int fd, ret, i, size, exit_code = -1;
+ k_rtsigset_t mask;
+ siginfo_t *infos;
+ unsigned long infos_size = PAGE_SIZE;
+ int flags = arg->group ? SFD_GROUP : SFD_PRIVATE;
+ long ptr;
+
+ ksigfillset(&mask);
+
+ ptr = sys_mmap(NULL, infos_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+ if ((long)ptr < 0) {
+ pr_err("mmap() returned %ld\n", (long) ptr);
+ return -1;
+ }
+ infos = (void *) ptr;
+
+ fd = sys_signalfd(-1, &mask, sizeof(rt_sigset_t),
+ SFD_RAW | O_NONBLOCK | flags);
+ if (fd < 0) {
+ pr_perror("signalfd returned %d\n", fd);
+ goto free;
+ }
+
+ size = 0;
+ while (1) {
+ ret = sys_read(fd, ((void *) infos) + size, PAGE_SIZE);
+ if (ret < 0)
+ break;
+
+ size += ret;
+ if (ret < PAGE_SIZE)
+ break;
+
+ ptr = sys_mremap((unsigned long) infos, infos_size,
+ infos_size + PAGE_SIZE, MREMAP_MAYMOVE, 0);
+ if ((long)infos < 0) {
+ pr_err("mremap() returned %ld\n", (long) ptr);
+ sys_close(fd);
+ goto free;
+ }
+ infos = (void *) ptr;
+ infos_size += PAGE_SIZE;
+ }
+ sys_close(fd);
+
+ if (ret < 0 && ret != -EAGAIN) {
+ pr_err("read() returned %d\n", ret);
+ 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);
+ if (arg->group)
+ ret = sys_rt_sigqueueinfo(sys_getpid(),
+ infos[i].si_signo, infos + i);
+ else
+ ret = sys_rt_tgsigqueueinfo(sys_getpid(), sys_gettid(),
+ infos[i].si_signo, infos + i);
+ if (ret < 0) {
+ pr_err("rt_sigqueueinfo() failed with code %d", ret);
+ return -1;
+ }
+ }
+
+ ret = sys_write(tsock, infos, size);
+ if (ret != size) {
+ pr_err("send() returned %d\n", ret);
+ goto free;
+ }
+
+ exit_code = size;
+free:
+ sys_munmap(infos, infos_size);
+ return exit_code;
+}
+
/*
* This is the main page dumping routine, it's executed
* inside a victim process space.
@@ -635,6 +717,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(args);
}
pr_err("Unknown command to parasite\n");
--
1.7.11.7
More information about the CRIU
mailing list