]> xenbits.xensource.com Git - qemu-xen.git/commitdiff
rcu: do not create thread in pthread_atfork callback
authorPaolo Bonzini <pbonzini@redhat.com>
Tue, 31 Mar 2015 11:01:05 +0000 (13:01 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 1 Apr 2015 08:06:38 +0000 (10:06 +0200)
If QEMU forks after the CPU threads have been created, qemu_mutex_lock_iothread
will not be able to do qemu_cpu_kick_thread.  There is no solution other than
assuming that forks after the CPU threads have been created will end up in an
exec.  Forks before the CPU threads have been created (such as -daemonize)
have to call rcu_after_fork manually.

Notably, the oxygen theme for GTK+ forks and shows a "No such process" error
without this patch.

This patch can be reverted once the iothread loses the "kick the TCG thread"
magic.

User-mode emulation does not use the iothread, so it can also call
rcu_after_fork.

Reported by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Tested by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
include/qemu/rcu.h
linux-user/syscall.c
os-posix.c
util/rcu.c

index 506ab58eaf0fda84d3d9c3e22e27c8eaddd11e5c..7df1e86622f2cd8b8aefa2290e05cb4f6aed43ae 100644 (file)
@@ -117,6 +117,7 @@ extern void synchronize_rcu(void);
  */
 extern void rcu_register_thread(void);
 extern void rcu_unregister_thread(void);
+extern void rcu_after_fork(void);
 
 struct rcu_head;
 typedef void RCUCBFunc(struct rcu_head *head);
index 4bd954375e7968eb46ac5d1fbc3f7dc1e9debd67..1622ad64905eefb31fb4d49cc330242a2aea7ba0 100644 (file)
@@ -4572,6 +4572,7 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
         ret = fork();
         if (ret == 0) {
             /* Child Process.  */
+            rcu_after_fork();
             cpu_clone_regs(env, newsp);
             fork_end(1);
             /* There is a race condition here.  The parent process could
index ba091f1530bfaf6d3a59b720bdb6412058f17b67..e4da406f38ca0c63a43db09d2ee8ccb017e1b7ec 100644 (file)
@@ -39,6 +39,7 @@
 #include "sysemu/sysemu.h"
 #include "net/slirp.h"
 #include "qemu-options.h"
+#include "qemu/rcu.h"
 
 #ifdef CONFIG_LINUX
 #include <sys/prctl.h>
@@ -247,6 +248,7 @@ void os_daemonize(void)
         signal(SIGTSTP, SIG_IGN);
         signal(SIGTTOU, SIG_IGN);
         signal(SIGTTIN, SIG_IGN);
+        rcu_after_fork();
     }
 }
 
index 27802a4bed4e83d4cbfd4f6f34646f4644cb3a1e..7270151befc7031bd7067748979aa60c8f9d40b2 100644 (file)
@@ -311,19 +311,18 @@ static void rcu_init_unlock(void)
 {
     qemu_mutex_unlock(&rcu_gp_lock);
 }
+#endif
 
-static void rcu_init_child(void)
+void rcu_after_fork(void)
 {
-    qemu_mutex_unlock(&rcu_gp_lock);
     memset(&registry, 0, sizeof(registry));
     rcu_init_complete();
 }
-#endif
 
 static void __attribute__((__constructor__)) rcu_init(void)
 {
 #ifdef CONFIG_POSIX
-    pthread_atfork(rcu_init_lock, rcu_init_unlock, rcu_init_child);
+    pthread_atfork(rcu_init_lock, rcu_init_unlock, rcu_init_unlock);
 #endif
     rcu_init_complete();
 }