[CRIU] [PATCH 05/10] crtools: dump pending signals (v3)
Andrey Vagin
avagin at openvz.org
Tue Mar 5 09:54:37 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
v3: rework according with the newrest kernel interface
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
cr-dump.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
include/ptrace.h | 13 +++++++++++
2 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/cr-dump.c b/cr-dump.c
index aff3e0c..8b10f6f 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -28,6 +28,7 @@
#include "protobuf/core.pb-c.h"
#include "protobuf/file-lock.pb-c.h"
#include "protobuf/rlimit.pb-c.h"
+#include "protobuf/siginfo.pb-c.h"
#include "asm/types.h"
#include "list.h"
@@ -1164,6 +1165,62 @@ err:
return ret;
}
+static int dump_signal_queue(pid_t tid, int fd, bool group)
+{
+ struct ptrace_peeksiginfo_args arg;
+ siginfo_t siginfo[32]; /* One page or all non-rt signals */
+ int ret, i = 0, j, nr;
+
+ arg.nr = sizeof(siginfo) / sizeof(siginfo_t);
+ arg.flags = 0;
+ if (group)
+ arg.flags |= PTRACE_PEEKSIGINFO_SHARED;
+
+ for (; ; ) {
+ arg.off = i;
+
+ ret = ptrace(PTRACE_PEEKSIGINFO, tid, &arg, siginfo);
+ if (ret <= 0)
+ break;
+ nr = ret;
+
+ for (j = 0; j < nr; j++) {
+ SiginfoEntry sie = SIGINFO_ENTRY__INIT;
+
+ sie.siginfo.len = sizeof(siginfo_t);
+ sie.siginfo.data = (void *) (siginfo + j);
+
+ ret = pb_write_one(fd, &sie, PB_SIGINFO);
+ if (ret < 0)
+ break;
+ i++;
+ }
+ if (ret < 0) {
+ if (errno == EIO) {
+ pr_warn("ptrace doesn't support PTRACE_PEEKSIGINFO\n");
+ ret = 0;
+ } else
+ pr_perror("ptrace");
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int dump_thread_signals(struct pid *tid)
+{
+ int fd, ret;
+
+ fd = open_image(CR_FD_PSIGNAL, O_DUMP, tid->virt);
+ if (fd < 0)
+ return -1;
+ ret = dump_signal_queue(tid->real, fd, 0);
+ close(fd);
+
+ return ret;
+}
+
static struct proc_pid_stat pps_buf;
static int dump_task_threads(struct parasite_ctl *parasite_ctl,
@@ -1173,12 +1230,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_thread_signals(&item->threads[i]))
return -1;
}
@@ -1428,6 +1487,12 @@ static int dump_one_task(struct pstree_item *item)
goto err;
}
+ ret = dump_signal_queue(pid, fdset_fd(cr_fdset, CR_FD_SIGNAL), 1);
+ if (ret) {
+ pr_err("Can't dump pending signals (pid: %d)\n", pid);
+ goto err_cure;
+ }
+
close_cr_fdset(&cr_fdset);
err:
close_pid_proc();
diff --git a/include/ptrace.h b/include/ptrace.h
index ea45d20..4d1bc92 100644
--- a/include/ptrace.h
+++ b/include/ptrace.h
@@ -1,6 +1,7 @@
#ifndef __CR_SEIZE_H__
#define __CR_SEIZE_H__
+#include <linux/types.h>
#include <sys/ptrace.h>
/* some constants for ptrace */
@@ -14,6 +15,18 @@
#define PTRACE_LISTEN 0x4208
+#ifndef PTRACE_PEEKSIGINFO
+#define PTRACE_PEEKSIGINFO 0x4209
+struct ptrace_peeksiginfo_args {
+ __u64 off; /* from which siginfo to start */
+ __u32 flags;
+ __u32 nr; /* how may siginfos to take */
+};
+
+/* Read signals from a shared (process wide) queue */
+#define PTRACE_PEEKSIGINFO_SHARED (1 << 0)
+#endif
+
#define PTRACE_SEIZE_DEVEL 0x80000000
#define PTRACE_EVENT_FORK 1
--
1.7.11.7
More information about the CRIU
mailing list