[CRIU] [PATCH 12/24] dump: return signal mask from parasite on initialization

Andrey Vagin avagin at openvz.org
Wed May 22 16:08:13 EDT 2013


and check that signals are blocked for each thread separately

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 arch/arm/crtools.c         |  2 +-
 arch/x86/crtools.c         |  2 +-
 cr-dump.c                  | 10 +++++++---
 include/parasite-syscall.h |  8 +++++---
 include/parasite.h         |  3 ++-
 parasite-syscall.c         | 33 +++++++++++++++++++++++++--------
 pie/parasite.c             | 13 ++++++-------
 7 files changed, 47 insertions(+), 24 deletions(-)

diff --git a/arch/arm/crtools.c b/arch/arm/crtools.c
index 04079db..6d97e3f 100644
--- a/arch/arm/crtools.c
+++ b/arch/arm/crtools.c
@@ -75,7 +75,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
 
 	parasite_setup_regs(ctl->syscall_ip, &regs);
 	err = __parasite_execute_trap(ctl, ctl->pid.real, &regs,
-					&ctl->threads[0].regs_orig);
+					&ctl->threads[0].regs_orig, 0);
 	if (err)
 		return err;
 
diff --git a/arch/x86/crtools.c b/arch/x86/crtools.c
index 8d12031..90e1290 100644
--- a/arch/x86/crtools.c
+++ b/arch/x86/crtools.c
@@ -99,7 +99,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
 
 	parasite_setup_regs(ctl->syscall_ip, &regs);
 	err = __parasite_execute_trap(ctl, ctl->pid.real, &regs,
-					&ctl->threads[0].regs_orig);
+					&ctl->threads[0].regs_orig, 0);
 	if (err)
 		return err;
 
diff --git a/cr-dump.c b/cr-dump.c
index 278407b..cf36e8b 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -630,6 +630,7 @@ static int dump_task_core_all(struct parasite_ctl *ctl,
 		struct vm_area_list *vma_area_list,
 		const struct cr_fdset *cr_fdset)
 {
+	k_rtsigset_t *sig_blocked = &ctl->threads[0].sig_blocked;
 	int fd_core = fdset_fd(cr_fdset, CR_FD_CORE);
 	int ret = -1;
 	pid_t pid = ctl->pid.real;
@@ -655,7 +656,7 @@ static int dump_task_core_all(struct parasite_ctl *ctl,
 	strncpy((char *)core->tc->comm, stat->comm, TASK_COMM_LEN);
 	core->tc->flags = stat->flags;
 	BUILD_BUG_ON(sizeof(core->tc->blk_sigset) != sizeof(k_rtsigset_t));
-	memcpy(&core->tc->blk_sigset, &misc->blocked, sizeof(k_rtsigset_t));
+	memcpy(&core->tc->blk_sigset, sig_blocked, sizeof(k_rtsigset_t));
 
 	core->tc->task_state = TASK_ALIVE;
 	core->tc->exit_code = 0;
@@ -1077,7 +1078,8 @@ static int collect_file_locks(void)
 }
 
 static int dump_task_thread(struct parasite_ctl *parasite_ctl,
-			    struct pid *tid, CoreEntry *core)
+			    struct pid *tid, CoreEntry *core,
+			    k_rtsigset_t *sig_blocked)
 {
 	int ret = -1, fd_core;
 	pid_t pid = tid->real;
@@ -1097,6 +1099,7 @@ static int dump_task_thread(struct parasite_ctl *parasite_ctl,
 	}
 
 	core->thread_core->has_blk_sigset = true;
+	memcpy(&core->thread_core->blk_sigset, sig_blocked, sizeof(*sig_blocked));
 
 	ret = dump_sched_info(pid, core->thread_core);
 	if (ret)
@@ -1210,7 +1213,8 @@ static int dump_task_threads(struct parasite_ctl *parasite_ctl,
 			item->threads[i].virt = item->pid.virt;
 			continue;
 		}
-		if (dump_task_thread(parasite_ctl, &item->threads[i], item->core[i]))
+		if (dump_task_thread(parasite_ctl, &item->threads[i], item->core[i],
+					&parasite_ctl->threads[i].sig_blocked))
 			return -1;
 	}
 
diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index cce5680..e4b0618 100644
--- a/include/parasite-syscall.h
+++ b/include/parasite-syscall.h
@@ -10,6 +10,9 @@ struct parasite_thread_ctl
 	pid_t			tid;
 	user_regs_struct_t	regs_orig;				/* original registers */
 	bool			daemonized;
+
+	k_rtsigset_t		sig_blocked;
+	bool			use_sig_blocked;
 };
 
 /* parasite control block */
@@ -23,8 +26,6 @@ struct parasite_ctl {
 	unsigned long		syscall_ip;				/* entry point of infection */
 	u8			code_orig[BUILTIN_SYSCALL_SIZE];
 
-	int			signals_blocked;
-
 	unsigned int		*addr_cmd;				/* addr for command */
 	void			*addr_args;				/* address for arguments */
 	unsigned long		args_size;
@@ -101,6 +102,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
 extern bool arch_can_dump_task(pid_t pid);
 extern int __parasite_execute_trap(struct parasite_ctl *ctl, pid_t pid,
 					user_regs_struct_t *regs,
-					user_regs_struct_t *regs_orig);
+					user_regs_struct_t *regs_orig,
+					bool signals_blocked);
 
 #endif /* __CR_PARASITE_SYSCALL_H__ */
diff --git a/include/parasite.h b/include/parasite.h
index 22148e2..4040034 100644
--- a/include/parasite.h
+++ b/include/parasite.h
@@ -71,6 +71,8 @@ struct parasite_init_args {
 
 	int			nr_threads;
 	pid_t			real;
+
+	k_rtsigset_t		sig_blocked;
 };
 
 struct parasite_log_args {
@@ -119,7 +121,6 @@ struct parasite_dump_itimers_args {
 
 struct parasite_dump_misc {
 	unsigned long		brk;
-	k_rtsigset_t		blocked;
 
 	u32 pid;
 	u32 sid;
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 0452e4f..af21184 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -63,7 +63,8 @@ static struct vma_area *get_vma_by_ip(struct list_head *vma_area_list, unsigned
 /* we run at @regs->ip */
 int __parasite_execute_trap(struct parasite_ctl *ctl, pid_t pid,
 				user_regs_struct_t *regs,
-				user_regs_struct_t *regs_orig)
+				user_regs_struct_t *regs_orig,
+				bool signals_blocked)
 {
 	siginfo_t siginfo;
 	int status;
@@ -110,7 +111,7 @@ retry_signal:
 		pr_debug("** delivering signal %d si_code=%d\n",
 			 siginfo.si_signo, siginfo.si_code);
 
-		if (ctl->signals_blocked) {
+		if (signals_blocked) {
 			pr_err("Unexpected %d task interruption, aborting\n", pid);
 			goto err;
 		}
@@ -208,7 +209,8 @@ static int parasite_execute_trap_by_pid(unsigned int cmd, struct parasite_ctl *c
 
 	parasite_setup_regs(ctl->parasite_ip, &regs);
 
-	ret = __parasite_execute_trap(ctl, pid, &regs, &thread->regs_orig);
+	ret = __parasite_execute_trap(ctl, pid, &regs, &thread->regs_orig,
+					thread->use_sig_blocked);
 	if (ret == 0)
 		ret = (int)REG_RES(regs);
 
@@ -431,6 +433,9 @@ static int parasite_init(struct parasite_ctl *ctl, pid_t pid, int nr_threads)
 		goto err;
 	}
 
+	ctl->threads[0].sig_blocked = args->sig_blocked;
+	ctl->threads[0].use_sig_blocked = true;
+
 	if (connect(sock, (struct sockaddr *)&args->p_addr, args->p_addr_len) < 0) {
 		pr_perror("Can't connect a transport socket");
 		goto err;
@@ -493,7 +498,6 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, struct pid *tid,
 
 	ret = parasite_execute_daemon_by_pid(PARASITE_CMD_DUMP_THREAD, ctl, tid->real);
 
-	memcpy(&core->thread_core->blk_sigset, &args->blocked, sizeof(args->blocked));
 	CORE_THREAD_ARCH_INFO(core)->clear_tid_addr = encode_pointer(args->tid_addr);
 	tid->virt = args->tid;
 	core_put_tls(core, args->tls);
@@ -697,6 +701,9 @@ int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i
 			goto err;
 		}
 
+		ctl->threads[i].sig_blocked = args->sig_blocked;
+		ctl->threads[i].use_sig_blocked = true;
+
 		if (parasite_daemonize(ctl, i))
 			goto err;
 	}
@@ -789,7 +796,6 @@ int parasite_cure_remote(struct parasite_ctl *ctl)
 	int ret = 0;
 
 	if (ctl->parasite_ip) {
-		ctl->signals_blocked = 0;
 		ret = parasite_fini_threads_seized(ctl);
 		parasite_fini_seized(ctl);
 	}
@@ -946,7 +952,7 @@ static unsigned long parasite_args_size(struct vm_area_list *vmas, struct parasi
 struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
 		struct vm_area_list *vma_area_list, struct parasite_drain_fd *dfds)
 {
-	int ret;
+	int ret, i;
 	struct parasite_ctl *ctl;
 
 	BUG_ON(item->threads[0].real != pid);
@@ -990,8 +996,6 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
 		goto err_restore;
 	}
 
-	ctl->signals_blocked = 1;
-
 	ret = parasite_set_logfd(ctl, pid);
 	if (ret) {
 		pr_err("%d: Can't set a logging descriptor\n", pid);
@@ -1005,6 +1009,19 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
 	if (ret)
 		goto err_restore;
 
+	for (i = 0; i < item->nr_threads; i++) {
+		struct parasite_thread_ctl *thread = &ctl->threads[i];
+
+		if (i == 0)
+			memcpy(&item->core[i]->tc->blk_sigset,
+				&thread->sig_blocked, sizeof(k_rtsigset_t));
+		else {
+			memcpy(&item->core[i]->thread_core->blk_sigset,
+				&thread->sig_blocked, sizeof(k_rtsigset_t));
+			item->core[i]->thread_core->has_blk_sigset = true;
+		}
+	}
+
 	return ctl;
 
 err_restore:
diff --git a/pie/parasite.c b/pie/parasite.c
index c2f721c..1d5f8d7 100644
--- a/pie/parasite.c
+++ b/pie/parasite.c
@@ -125,7 +125,6 @@ static int dump_itimers(struct parasite_dump_itimers_args *args)
 static int dump_misc(struct parasite_dump_misc *args)
 {
 	args->brk = sys_brk(0);
-	args->blocked = thread_leader->sig_blocked;
 
 	args->pid = sys_getpid();
 	args->sid = sys_getsid();
@@ -214,14 +213,10 @@ static int dump_thread(struct parasite_dump_thread *args)
 	if (!s)
 		return -ENOENT;
 
-	if (!s->use_sig_blocked)
-		return -EINVAL;
-
 	ret = sys_prctl(PR_GET_TID_ADDRESS, (unsigned long) &args->tid_addr, 0, 0, 0);
 	if (ret)
 		return ret;
 
-	args->blocked = s->sig_blocked;
 	args->tid = tid;
 	args->tls = arch_get_tls();
 
@@ -240,8 +235,12 @@ static int init_thread(struct parasite_init_args *args)
 	ret = sys_sigprocmask(SIG_SETMASK, &to_block,
 			      &tid_state[next_tid_state].sig_blocked,
 			      sizeof(k_rtsigset_t));
-	if (ret >= 0)
-		tid_state[next_tid_state].use_sig_blocked = true;
+	if (ret)
+		return -1;
+
+	tid_state[next_tid_state].use_sig_blocked = true;
+	args->sig_blocked = tid_state[next_tid_state].sig_blocked;
+
 	tid_state[next_tid_state].tid = sys_gettid();
 	tid_state[next_tid_state].real = args->real;
 
-- 
1.8.2



More information about the CRIU mailing list