Commit bae333df authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

restorer: fix a race condition between access and unmap to task_entries

If we have tree threads, a following situation can occur:

T2: dec task_entries->nr_in_progress
T3: dec task_entries->nr_in_progress
T3: futex(&task_entries->nr_in_progress, WAKE_UP);
T1: unmap task_entries
T2: futex(&task_entries->nr_in_progress, WAKE_UP) -> EFAULT -> BUG_ON()

This patch adds a futex for synchronising threads.
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 6b1d64ca
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
}) })
static struct task_entries *task_entries; static struct task_entries *task_entries;
static futex_t thread_inprogress;
static void sigchld_handler(int signal, siginfo_t *siginfo, void *data) static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
{ {
...@@ -237,6 +238,8 @@ long __export_restore_thread(struct thread_restore_args *args) ...@@ -237,6 +238,8 @@ long __export_restore_thread(struct thread_restore_args *args)
futex_wait_while(&task_entries->start, CR_STATE_RESTORE); futex_wait_while(&task_entries->start, CR_STATE_RESTORE);
futex_dec_and_wake(&task_entries->nr_in_progress); futex_dec_and_wake(&task_entries->nr_in_progress);
futex_wait_while(&task_entries->start, CR_STATE_RESTORE_SIGCHLD);
futex_dec_and_wake(&thread_inprogress);
new_sp = (long)rt_sigframe + 8; new_sp = (long)rt_sigframe + 8;
asm volatile( asm volatile(
...@@ -737,10 +740,15 @@ long __export_restore_task(struct task_restore_core_args *args) ...@@ -737,10 +740,15 @@ long __export_restore_task(struct task_restore_core_args *args)
sys_sigaction(SIGCHLD, &args->sigchld_act, NULL, sizeof(rt_sigset_t)); sys_sigaction(SIGCHLD, &args->sigchld_act, NULL, sizeof(rt_sigset_t));
futex_set_and_wake(&thread_inprogress, args->nr_threads);
futex_dec_and_wake(&args->task_entries->nr_in_progress); futex_dec_and_wake(&args->task_entries->nr_in_progress);
futex_wait_while(&args->task_entries->start, CR_STATE_RESTORE_SIGCHLD); futex_wait_while(&args->task_entries->start, CR_STATE_RESTORE_SIGCHLD);
/* Wait until children stop to use args->task_entries */
futex_wait_while_gt(&thread_inprogress, 1);
rst_tcp_socks_all(args->rst_tcp_socks, args->rst_tcp_socks_size); rst_tcp_socks_all(args->rst_tcp_socks, args->rst_tcp_socks_size);
log_set_fd(-1); log_set_fd(-1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment