Module: xenomai-jki
Branch: for-forge
Commit: 17ff57ad6c75bdca3a442a8d06ff89510a2e421a
URL:    
http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=17ff57ad6c75bdca3a442a8d06ff89510a2e421a

Author: Jan Kiszka <jan.kis...@siemens.com>
Date:   Mon Jan  5 15:48:14 2015 +0100

lib/cobalt: Fix ordering of fork handler

Currently, fork handlers run in more or less random order after
successive forks because pthread_atfork is re-executed for some
handlers. This can cause the heap being unmapped after __init_cobalt was
executed, leaving cobalt_current_window in an invalid state. One result
of this is a crashing sysregd when run as unprivileged user, thus when
it forked fusermount from the forked daemon.

Fix the issue by performing the after-fork work centrally, in a
well-defined order.

Signed-off-by: Jan Kiszka <jan.kis...@siemens.com>

---

 lib/cobalt/current.c  |    8 ++------
 lib/cobalt/current.h  |    2 ++
 lib/cobalt/init.c     |   29 +++++++++++++++++++----------
 lib/cobalt/internal.h |    2 ++
 lib/cobalt/printf.c   |    3 +--
 lib/cobalt/umm.c      |    4 +---
 lib/cobalt/umm.h      |    2 ++
 7 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/lib/cobalt/current.c b/lib/cobalt/current.c
index b7d5b6e..a8bc330 100644
--- a/lib/cobalt/current.c
+++ b/lib/cobalt/current.c
@@ -26,8 +26,6 @@
 
 static DEFINE_PRIVATE_LIST(tsd_hooks);
 
-static void child_fork_handler(void);
-
 #ifdef HAVE_TLS
 
 __thread __attribute__ ((tls_model (CONFIG_XENO_TLS_MODEL)))
@@ -53,7 +51,7 @@ static inline void __cobalt_clear_tsd(void)
 
 static void init_current_keys(void)
 {
-       pthread_atfork(NULL, NULL, &child_fork_handler);
+       cobalt_current = XN_NO_HANDLE;
 }
 
 #else /* !HAVE_TLS */
@@ -85,8 +83,6 @@ static void init_current_keys(void)
        if (err)
                goto error_exit;
 
-       pthread_atfork(NULL, NULL, &child_fork_handler);
-
        err = pthread_key_create(&cobalt_current_window_key, NULL);
        if (err) {
          error_exit:
@@ -97,7 +93,7 @@ static void init_current_keys(void)
 
 #endif /* !HAVE_TLS */
 
-static void child_fork_handler(void)
+void cobalt_clear_tsd(void)
 {
        struct cobalt_tsd_hook *th;
 
diff --git a/lib/cobalt/current.h b/lib/cobalt/current.h
index 3e28b83..069ee1c 100644
--- a/lib/cobalt/current.h
+++ b/lib/cobalt/current.h
@@ -93,4 +93,6 @@ void cobalt_init_current_keys(void);
 
 void cobalt_set_tsd(__u32 u_winoff);
 
+void cobalt_clear_tsd(void);
+
 #endif /* _LIB_COBALT_CURRENT_H */
diff --git a/lib/cobalt/init.c b/lib/cobalt/init.c
index dfe1150..b7c8f76 100644
--- a/lib/cobalt/init.c
+++ b/lib/cobalt/init.c
@@ -107,6 +107,24 @@ static void low_init(void)
 
 static void __init_cobalt(void);
 
+static void cobalt_fork_handler(void)
+{
+       cobalt_unmap_umm();
+       cobalt_clear_tsd();
+       cobalt_print_init_atfork();
+#ifdef HAVE_PTHREAD_ATFORK
+       /*
+        * Upon fork, in case the parent required init deferral, this
+        * is the forkee's responsibility to call __libcobalt_init()
+        * for bootstrapping the services the same way. On systems
+        * with no fork() support, clients are not supposed to, well,
+        * fork in the first place, so we don't take any provision for
+        * this event.
+        */
+       __init_cobalt();
+#endif
+}
+
 void __libcobalt_init(void)
 {
        struct sigaction sa;
@@ -118,21 +136,12 @@ void __libcobalt_init(void)
        sa.sa_flags = SA_SIGINFO;
        sigaction(SIGDEBUG, &sa, &__cobalt_orig_sigdebug);
 
-#ifdef HAVE_PTHREAD_ATFORK
        /*
-        * Upon fork, in case the parent required init deferral, this
-        * is the forkee's responsibility to call __libcobalt_init()
-        * for bootstrapping the services the same way. On systems
-        * with no fork() support, clients are not supposed to, well,
-        * fork in the first place, so we don't take any provision for
-        * this event.
-        *
         * NOTE: a placeholder for pthread_atfork() may return an
         * error status with uClibc, so we don't check the return
         * value on purpose.
         */
-       pthread_atfork(NULL, NULL, __init_cobalt);
-#endif
+       pthread_atfork(NULL, NULL, cobalt_fork_handler);
 
        if (sizeof(struct cobalt_mutex_shadow) > sizeof(pthread_mutex_t)) {
                report_error("sizeof(pthread_mutex_t): %d <"
diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
index c7350be..e126480 100644
--- a/lib/cobalt/internal.h
+++ b/lib/cobalt/internal.h
@@ -45,6 +45,8 @@ void cobalt_thread_init(void);
 
 void cobalt_print_init(void);
 
+void cobalt_print_init_atfork(void);
+
 void cobalt_print_exit(void);
 
 void cobalt_ticks_init(unsigned long long freq);
diff --git a/lib/cobalt/printf.c b/lib/cobalt/printf.c
index e391f96..f19f4ea 100644
--- a/lib/cobalt/printf.c
+++ b/lib/cobalt/printf.c
@@ -670,7 +670,7 @@ static void spawn_printer_thread(void)
        pthread_create(&printer_thread, &thattr, printer_loop, NULL);
 }
 
-static void forked_child_init(void)
+void cobalt_print_init_atfork(void)
 {
        struct print_buffer *my_buffer = pthread_getspecific(buffer_key);
        struct print_buffer **pbuffer = &first_buffer;
@@ -791,7 +791,6 @@ void cobalt_print_init(void)
        pthread_cond_init(&printer_wakeup, NULL);
 
        spawn_printer_thread();
-       pthread_atfork(NULL, NULL, forked_child_init);
 
        rt_print_auto_init(1);
        atexit(rt_print_flush_buffers);
diff --git a/lib/cobalt/umm.c b/lib/cobalt/umm.c
index a09b2d6..4a881a3 100644
--- a/lib/cobalt/umm.c
+++ b/lib/cobalt/umm.c
@@ -75,7 +75,7 @@ static void *__map_umm(const char *name, uint32_t *size_r)
 
 #define map_umm(__name, __size_r)  __map_umm("/dev/rtdm/" __name, __size_r)
 
-static void unmap_on_fork(void)
+void cobalt_unmap_umm(void)
 {
        void *addr;
 
@@ -121,8 +121,6 @@ static void init_loadup(__u32 vdso_offset)
 {
        uint32_t size;
 
-       pthread_atfork(NULL, NULL, unmap_on_fork);
-
        cobalt_umm_shared = map_umm(COBALT_MEMDEV_SHARED, &size);
        if (cobalt_umm_shared == MAP_FAILED) {
                report_error("cannot map shared umm area: %s",
diff --git a/lib/cobalt/umm.h b/lib/cobalt/umm.h
index 5647758..b592968 100644
--- a/lib/cobalt/umm.h
+++ b/lib/cobalt/umm.h
@@ -22,6 +22,8 @@
 
 void cobalt_init_umm(__u32 vdso_offset);
 
+void cobalt_unmap_umm(void);
+
 struct xnvdso;
 
 extern struct xnvdso *cobalt_vdso;


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to