[Xenomai-git] Jan Kiszka : lib/cobalt: Fix ordering of fork handler
Module: xenomai-3 Branch: master Commit: c2ba8c32b5c81f0fba206fac53f175a419cf9fe3 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=c2ba8c32b5c81f0fba206fac53f175a419cf9fe3 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
[Xenomai-git] Jan Kiszka : lib/cobalt: Fix ordering of fork handler
Module: xenomai-3 Branch: next Commit: c2ba8c32b5c81f0fba206fac53f175a419cf9fe3 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=c2ba8c32b5c81f0fba206fac53f175a419cf9fe3 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
[Xenomai-git] Jan Kiszka : lib/cobalt: Fix ordering of fork handler
Module: xenomai-3 Branch: next Commit: 7e49bffaeba00fbcbd19daf6c87128581b08d1f6 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=7e49bffaeba00fbcbd19daf6c87128581b08d1f6 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
[Xenomai-git] Jan Kiszka : lib/cobalt: Fix ordering of fork handler
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)
[Xenomai-git] Jan Kiszka : lib/cobalt: Fix ordering of fork handler
Module: xenomai-jki Branch: for-forge Commit: 352877b343aaca70bc46a83d172f5eb080c53459 URL: http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=352877b343aaca70bc46a83d172f5eb080c53459 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)
[Xenomai-git] Jan Kiszka : lib/cobalt: Fix ordering of fork handler
Module: xenomai-jki Branch: for-forge Commit: d373c3a3ee1dd1cce7c6fe7d3b4205af0bfce5aa URL: http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=d373c3a3ee1dd1cce7c6fe7d3b4205af0bfce5aa 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)
[Xenomai-git] Jan Kiszka : lib/cobalt: Fix ordering of fork handler
Module: xenomai-jki Branch: for-forge Commit: ce93be10341beb8c1f7a59a462307f3f8a4aec0a URL: http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=ce93be10341beb8c1f7a59a462307f3f8a4aec0a 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. This could cause the heap being unmapped after __init_cobalt was executed, leaving cobalt_current_window in an invalid state. This caused, e.g., crashes of the sysregd when run as unprivileged user, thus when it forked to run fusermount with root privileges. 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