[CRIU] [crtools-bot for Pavel Emelyanov ] dump: Collect
mem+regs+sigmask atomically
Cyrill Gorcunov
gorcunov at openvz.org
Mon Feb 20 03:33:43 EST 2012
The commit is pushed to "master" and will appear on git://github.com/cyrillos/crtools.git
------>
commit 097bc0b9672cf97c87efc203de0e2cc33fa20f19
Author: Pavel Emelyanov <xemul at parallels.com>
Date: Fri Feb 17 22:56:36 2012 +0400
dump: Collect mem+regs+sigmask atomically
The ptrace seize doesn't prevent signals from delivery. That said,
we should block the signals in the target task before dumping
anything which is signals-related, i.e. memory and registers.
But once we've blocked signals, we should dump registers before
unblocking them, since any postponed signal will screw things up.
Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
cr-dump.c | 72 +++++++++++++++++------------------------------
include/parasite.h | 1 +
include/syscall-codes.h | 1 +
include/syscall.h | 7 ++++
include/types.h | 16 ++++++++++
parasite.c | 16 ++++++++++-
6 files changed, 66 insertions(+), 47 deletions(-)
diff --git a/cr-dump.c b/cr-dump.c
index 66f44ba..642755e 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -481,32 +481,6 @@ static int dump_task_creds(pid_t pid,
#define assign_reg(dst, src, e) dst.e = (__typeof__(dst.e))src.e
#define assign_array(dst, src, e) memcpy(&dst.e, &src.e, sizeof(dst.e))
-static int get_task_sigmask(pid_t pid, u64 *task_sigset)
-{
- FILE *file;
- int ret = -1;
-
- /*
- * Now signals.
- */
- file = fopen_proc(pid, "status");
- if (!file)
- goto err;
-
- while (fgets(loc_buf, sizeof(loc_buf), file)) {
- if (!strncmp(loc_buf, "SigBlk:", 7)) {
- char *end;
- *task_sigset = strtol(&loc_buf[8], &end, 16);
- ret = 0;
- break;
- }
- }
-
- fclose(file);
-err:
- return ret;
-}
-
static int get_task_auxv(pid_t pid, struct core_entry *core)
{
int fd = open_proc(pid, "auxv");
@@ -558,15 +532,19 @@ err:
return ret;
}
-static int get_task_regs(pid_t pid, struct core_entry *core)
+static int get_task_regs(pid_t pid, struct core_entry *core, struct parasite_ctl *ctl)
{
user_fpregs_struct_t fpregs = {-1};
user_regs_struct_t regs = {-1};
int ret = -1;
- if (ptrace(PTRACE_GETREGS, pid, NULL, ®s)) {
- pr_err("Can't obtain GP registers for %d\n", pid);
- goto err;
+ if (ctl)
+ regs = ctl->regs_orig;
+ else {
+ if (ptrace(PTRACE_GETREGS, pid, NULL, ®s)) {
+ pr_err("Can't obtain GP registers for %d\n", pid);
+ goto err;
+ }
}
if (ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs)) {
@@ -658,7 +636,8 @@ static int dump_task_core(struct core_entry *core, struct cr_fdset *fdset)
}
static int dump_task_core_all(pid_t pid, struct proc_pid_stat *stat,
- struct parasite_dump_misc *misc, struct cr_fdset *cr_fdset)
+ struct parasite_dump_misc *misc, struct parasite_ctl *ctl,
+ struct cr_fdset *cr_fdset)
{
struct core_entry *core = xzalloc(sizeof(*core));
int ret = -1;
@@ -672,7 +651,7 @@ static int dump_task_core_all(pid_t pid, struct proc_pid_stat *stat,
goto err;
pr_info("Dumping GP/FPU registers ... ");
- ret = get_task_regs(pid, core);
+ ret = get_task_regs(pid, core, ctl);
if (ret)
goto err_free;
pr_info("OK\n");
@@ -699,11 +678,8 @@ static int dump_task_core_all(pid_t pid, struct proc_pid_stat *stat,
core->tc.mm_brk = misc->brk;
- pr_info("Obtainting sigmask ... ");
- ret = get_task_sigmask(pid, &core->tc.blk_sigset);
- if (ret)
- goto err_free;
- pr_info("OK\n");
+ BUILD_BUG_ON(sizeof(core->tc.blk_sigset) != sizeof(k_rtsigset_t));
+ memcpy(&core->tc.blk_sigset, &misc->blocked, sizeof(k_rtsigset_t));
pr_info("Obtainting task auvx ... ");
ret = get_task_auxv(pid, core);
@@ -1066,7 +1042,7 @@ static int dump_task_thread(pid_t pid, struct cr_fdset *cr_fdset)
goto err;
pr_info("Dumping GP/FPU registers ... ");
- ret = get_task_regs(pid, core);
+ ret = get_task_regs(pid, core, NULL);
if (ret)
goto err_free;
if (ptrace(PTRACE_GET_TID_ADDRESS, pid, NULL, &core->clear_tid_address)) {
@@ -1204,6 +1180,18 @@ static int dump_one_task(struct pstree_item *item, struct cr_fdset *cr_fdset)
goto err;
}
+ ret = dump_task_core_all(pid, &pps_buf, &misc, parasite_ctl, cr_fdset);
+ if (ret) {
+ pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
+ goto err;
+ }
+
+ ret = dump_task_threads(item);
+ if (ret) {
+ pr_err("Can't dump threads\n");
+ goto err;
+ }
+
ret = parasite_cure_seized(parasite_ctl);
if (ret) {
pr_err("Can't cure (pid: %d) from parasite\n", pid);
@@ -1228,12 +1216,6 @@ static int dump_one_task(struct pstree_item *item, struct cr_fdset *cr_fdset)
goto err;
}
- ret = dump_task_core_all(pid, &pps_buf, &misc, cr_fdset);
- if (ret) {
- pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
- goto err;
- }
-
ret = finalize_core(pid, &vma_area_list, cr_fdset);
if (ret) {
pr_err("Finalizing core (pid: %d) failed with %d\n", pid, ret);
@@ -1242,8 +1224,6 @@ static int dump_one_task(struct pstree_item *item, struct cr_fdset *cr_fdset)
free_mappings(&vma_area_list);
- ret = dump_task_threads(item);
-
err:
close_pid_proc();
err_free:
diff --git a/include/parasite.h b/include/parasite.h
index 96b78c1..59eff7d 100644
--- a/include/parasite.h
+++ b/include/parasite.h
@@ -87,6 +87,7 @@ struct parasite_dump_misc {
unsigned int secbits;
unsigned long brk;
+ k_rtsigset_t blocked;
};
/*
diff --git a/include/syscall-codes.h b/include/syscall-codes.h
index 28def99..2a470c6 100644
--- a/include/syscall-codes.h
+++ b/include/syscall-codes.h
@@ -13,6 +13,7 @@
#define __NR_munmap 11
#define __NR_brk 12
#define __NR_rt_sigaction 13
+#define __NR_rt_sigprocmask 14
#define __NR_rt_sigreturn 15
#define __NR_mincore 27
#define __NR_shmat 30
diff --git a/include/syscall.h b/include/syscall.h
index 02e5ee6..f759587 100644
--- a/include/syscall.h
+++ b/include/syscall.h
@@ -241,6 +241,13 @@ static always_inline long sys_rt_sigreturn(void)
return syscall0(__NR_rt_sigreturn);
}
+static always_inline long sys_sigprocmask(int how, k_rtsigset_t *set,
+ k_rtsigset_t *old)
+{
+ return syscall4(__NR_rt_sigprocmask, how, (unsigned long)set,
+ (unsigned long)old, (unsigned long)sizeof(k_rtsigset_t));
+}
+
static always_inline long sys_set_thread_area(user_desc_t *info)
{
return syscall1(__NR_set_thread_area, (long)info);
diff --git a/include/types.h b/include/types.h
index 5d93dac..dea51e1 100644
--- a/include/types.h
+++ b/include/types.h
@@ -98,6 +98,22 @@ typedef struct {
rt_sigset_t rt_sa_mask;
} rt_sigaction_t;
+#define _KNSIG 64
+# define _NSIG_BPW 64
+
+#define _KNSIG_WORDS (_KNSIG / _NSIG_BPW)
+
+typedef struct {
+ unsigned long sig[_KNSIG_WORDS];
+} k_rtsigset_t;
+
+static inline void ksigfillset(k_rtsigset_t *set)
+{
+ int i;
+ for (i = 0; i < _KNSIG_WORDS; i++)
+ set->sig[i] = (unsigned long)-1;
+}
+
typedef struct {
unsigned int entry_number;
unsigned int base_addr;
diff --git a/parasite.c b/parasite.c
index a77a94f..d77a24a 100644
--- a/parasite.c
+++ b/parasite.c
@@ -358,12 +358,16 @@ err_close:
return ret;
}
+static k_rtsigset_t old_blocked;
+static int reset_blocked = 0;
+
static int dump_misc(struct parasite_dump_misc *args)
{
parasite_status_t *st = &args->status;
args->secbits = sys_prctl(PR_GET_SECUREBITS, 0, 0, 0, 0);
args->brk = sys_brk(0);
+ args->blocked = old_blocked;
SET_PARASITE_STATUS(st, 0, 0);
return 0;
@@ -372,6 +376,7 @@ static int dump_misc(struct parasite_dump_misc *args)
static int init(struct parasite_init_args *args)
{
int ret;
+ k_rtsigset_t to_block;
tsock = sys_socket(PF_UNIX, SOCK_DGRAM, 0);
if (tsock < 0) {
@@ -383,7 +388,14 @@ static int init(struct parasite_init_args *args)
return -1;
}
- return 0;
+ ksigfillset(&to_block);
+ ret = sys_sigprocmask(SIG_SETMASK, &to_block, &old_blocked);
+ if (ret < 0)
+ reset_blocked = ret;
+ else
+ reset_blocked = 1;
+
+ return ret;
}
static int set_logfd()
@@ -394,6 +406,8 @@ static int set_logfd()
static int fini()
{
+ if (reset_blocked == 1)
+ sys_sigprocmask(SIG_SETMASK, &old_blocked, NULL);
sys_close(logfd);
sys_close(tsock);
return 0;
More information about the CRIU
mailing list