[CRIU] [PATCH 3/3] ptrace: try to get signal blocking mask via ptrace

Andrey Vagin avagin at openvz.org
Thu Jun 6 06:35:35 EDT 2013


Two new commands SETSIGMASK and GETSIGMASK were added to ptrace.

It allows to execute only one parasite command for dumping threads,
so unrecoverable window become smaller and performance is improved.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 parasite-syscall.c | 125 ++++++++++++++++++++++++++++++++++++++++-------------
 pie/parasite.c     |   2 +
 2 files changed, 98 insertions(+), 29 deletions(-)

diff --git a/parasite-syscall.c b/parasite-syscall.c
index b61c93f..a1be21e 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -471,10 +471,99 @@ err:
 	return -1;
 }
 
+int parasite_dump_thread_seized_old(struct parasite_ctl *ctl, int id,
+				struct pid *tid, CoreEntry *core)
+{
+	struct parasite_dump_thread *args;
+	user_regs_struct_t regs_orig;
+	pid_t pid = tid->real;
+	int ret;
+
+	args = parasite_args(ctl, struct parasite_dump_thread);
+
+	ret = ptrace(PTRACE_GETREGS, pid, NULL, &regs_orig);
+	if (ret) {
+		pr_perror("Can't obtain registers (pid: %d)", pid);
+		return -1;
+	}
+
+	ret = parasite_execute_trap_by_pid(PARASITE_CMD_INIT_THREAD, ctl,
+					pid, &regs_orig,
+					ctl->r_thread_stack, false);
+	if (ret) {
+		pr_err("Can't init thread in parasite %d\n", pid);
+		return -1;
+	}
+
+	ret = get_task_regs(pid, regs_orig, core);
+	if (ret)
+		pr_err("Can't obtain regs for thread %d\n", pid);
+
+	if (parasite_execute_trap_by_pid(PARASITE_CMD_FINI_THREAD, ctl,
+					pid, &regs_orig,
+					ctl->r_thread_stack, true)) {
+		pr_err("Can't init thread in parasite %d\n", pid);
+		return -1;
+	}
+	if (ret)
+		return -1;
+
+	memcpy(&core->thread_core->blk_sigset,
+		&args->blocked, sizeof(k_rtsigset_t));
+
+	core->thread_core->has_blk_sigset = true;
+	return 0;
+}
+
+int parasite_dump_thread_seized_new(struct parasite_ctl *ctl, int id,
+				struct pid *tid, CoreEntry *core)
+{
+	user_regs_struct_t regs_orig;
+	pid_t pid = tid->real;
+	k_rtsigset_t maskall;
+	int ret;
+
+	ksigfillset(&maskall);
+
+	ret = ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), &maskall);
+	if (ret) {
+		pr_perror("Can't get signal blocking mask for %d", pid);
+		return -1;
+	}
+
+	ret = ptrace(PTRACE_GETREGS, pid, NULL, &regs_orig);
+	if (ret) {
+		pr_perror("Can't obtain registers (pid: %d)", pid);
+		goto out;
+	}
+
+	ret = parasite_execute_trap_by_pid(PARASITE_CMD_DUMP_THREAD, ctl,
+					pid, &regs_orig,
+					ctl->r_thread_stack, false);
+	if (ret) {
+		pr_err("Can't init thread in parasite %d\n", pid);
+		goto out;
+	}
+
+	ret = get_task_regs(pid, regs_orig, core);
+	if (ret)
+		pr_err("Can't obtain regs for thread %d\n", pid);
+
+out:
+	if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t),
+					&core->thread_core->blk_sigset)) {
+		pr_perror("Can't restore signal blocking mask for %d", pid);
+		ret = -1;
+	}
+
+	return ret;
+}
+
 int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
 				struct pid *tid, CoreEntry *core)
 {
 	struct parasite_dump_thread *args;
+	pid_t pid = tid->real;
 	int ret;
 
 	args = parasite_args(ctl, struct parasite_dump_thread);
@@ -482,39 +571,17 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
 	if (id == 0)
 		ret = parasite_execute_daemon(PARASITE_CMD_DUMP_THREAD, ctl);
 	else {
-		pid_t pid = tid->real;
-		user_regs_struct_t regs_orig;
-
-		ret = ptrace(PTRACE_GETREGS, pid, NULL, &regs_orig);
+		ret = ptrace(PTRACE_GETSIGMASK, pid, sizeof(k_rtsigset_t),
+						&core->thread_core->blk_sigset);
 		if (ret) {
-			pr_perror("Can't obtain registers (pid: %d)", pid);
-			return -1;
-		}
+			pr_warn("ptrace can't get signal blocking mask for %d", pid);
+			ret = parasite_dump_thread_seized_old(ctl, id, tid, core);
+		} else {
+			core->thread_core->has_blk_sigset = true;
 
-		ret = parasite_execute_trap_by_pid(PARASITE_CMD_INIT_THREAD, ctl,
-						pid, &regs_orig,
-						ctl->r_thread_stack, false);
-		if (ret) {
-			pr_err("Can't init thread in parasite %d\n", pid);
-			return -1;
+			ret = parasite_dump_thread_seized_new(ctl, id, tid, core);
 		}
 
-		ret = get_task_regs(pid, regs_orig, core);
-		if (ret)
-			pr_err("Can't obtain regs for thread %d\n", pid);
-
-		if (parasite_execute_trap_by_pid(PARASITE_CMD_FINI_THREAD, ctl,
-						pid, &regs_orig,
-						ctl->r_thread_stack, true)) {
-			pr_err("Can't init thread in parasite %d\n", pid);
-			return -1;
-		}
-		if (ret)
-			return -1;
-
-		memcpy(&core->thread_core->blk_sigset,
-			&args->blocked, sizeof(k_rtsigset_t));
-		core->thread_core->has_blk_sigset = true;
 	}
 
 	CORE_THREAD_ARCH_INFO(core)->clear_tid_addr = encode_pointer(args->tid_addr);
diff --git a/pie/parasite.c b/pie/parasite.c
index e840960..6a02b9f 100644
--- a/pie/parasite.c
+++ b/pie/parasite.c
@@ -528,6 +528,8 @@ int __used parasite_service(unsigned int cmd, void *args)
 	switch (cmd) {
 	case PARASITE_CMD_INIT:
 		return init(args);
+	case PARASITE_CMD_DUMP_THREAD:
+		return dump_thread(args);
 	case PARASITE_CMD_INIT_THREAD:
 		return init_thread(args);
 	case PARASITE_CMD_FINI_THREAD:
-- 
1.8.2



More information about the CRIU mailing list