From a729d2730d9d30f6610e43f070cedd1d60ba022f Mon Sep 17 00:00:00 2001 From: qihao Date: Thu, 30 Mar 2023 17:58:32 +0800 Subject: [PATCH] plugins: make qemu_plugin_user_exit's locking order consistent with fork_start's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cheery-pick from 2bbbc1be8d9a21b25d0c80b9a7345074d54abd51 To fix potential deadlocks as reported by tsan. Signed-off-by: qihao_yewu Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Emilio Cota Message-Id: <20230111151628.320011-6-cota@braap.org> Signed-off-by: Alex Bennée Message-Id: <20230124180127.1881110-31-alex.bennee@linaro.org> --- plugins/core.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/plugins/core.c b/plugins/core.c index 792262da08..e935e3c0c9 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -500,10 +500,18 @@ void qemu_plugin_user_exit(void) enum qemu_plugin_event ev; CPUState *cpu; - QEMU_LOCK_GUARD(&plugin.lock); + /* + * Locking order: we must acquire locks in an order that is consistent + * with the one in fork_start(). That is: + * - start_exclusive(), which acquires qemu_cpu_list_lock, + * must be called before acquiring plugin.lock. + * - tb_flush(), which acquires mmap_lock(), must be called + * while plugin.lock is not held. + */ start_exclusive(); + qemu_rec_mutex_lock(&plugin.lock); /* un-register all callbacks except the final AT_EXIT one */ for (ev = 0; ev < QEMU_PLUGIN_EV_MAX; ev++) { if (ev != QEMU_PLUGIN_EV_ATEXIT) { @@ -514,12 +522,12 @@ void qemu_plugin_user_exit(void) } } - tb_flush(current_cpu); - CPU_FOREACH(cpu) { qemu_plugin_disable_mem_helpers(cpu); } + qemu_rec_mutex_unlock(&plugin.lock); + tb_flush(current_cpu); end_exclusive(); /* now it's safe to handle the exit case */ -- 2.27.0