Position independent code and global destructor order (devel/ice)

Konstantin Belousov kostikbel at gmail.com
Fri Dec 6 03:21:22 UTC 2013


On Fri, Dec 06, 2013 at 03:25:52AM +0100, Michael Gmelin wrote:
> I tested your patch on 10-BETA2 and 10-BETA3. I built our complete
> production environment from scratch, ran a huge number of unit and
> integration tests. Everything works as expected, including Ice's
> "Schwarz Counter" implementation
> (http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter).
> 
> So as far as I can tell this fixes the problem, while still
> accomplishing the goals of r211706.

Great, thank you.

I think that the patch can be further simplified.  From what I understand
about __cxa_finalize(3) protocol, confirmed by LSB, __cxa_finalize(NULL)
must only be called at the process exit, once.  Than, libc can use the
call as an indication of the final call to finalize, avoiding need for
help from rtld.

Please test the patch below.  It is enough to rebuild libc only.

diff --git a/lib/libc/stdlib/atexit.c b/lib/libc/stdlib/atexit.c
index 18c31c3..01d09fe 100644
--- a/lib/libc/stdlib/atexit.c
+++ b/lib/libc/stdlib/atexit.c
@@ -151,6 +151,8 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso)
 #pragma weak __pthread_cxa_finalize
 void __pthread_cxa_finalize(const struct dl_phdr_info *);
 
+static int global_exit;
+
 /*
  * Call all handlers registered with __cxa_atexit for the shared
  * object owning 'dso'.  Note: if 'dso' is NULL, then all remaining
@@ -164,10 +166,12 @@ __cxa_finalize(void *dso)
 	struct atexit_fn fn;
 	int n, has_phdr;
 
-	if (dso != NULL)
+	if (dso != NULL) {
 		has_phdr = _rtld_addr_phdr(dso, &phdr_info);
-	else
+	} else {
 		has_phdr = 0;
+		global_exit = 1;
+	}
 
 	_MUTEX_LOCK(&atexit_mutex);
 	for (p = __atexit; p; p = p->next) {
@@ -177,8 +181,9 @@ __cxa_finalize(void *dso)
 			fn = p->fns[n];
 			if (dso != NULL && dso != fn.fn_dso) {
 				/* wrong DSO ? */
-				if (!has_phdr || !__elf_phdr_match_addr(
-				    &phdr_info, fn.fn_ptr.cxa_func))
+				if (!has_phdr || global_exit ||
+				    !__elf_phdr_match_addr(&phdr_info,
+				    fn.fn_ptr.cxa_func))
 					continue;
 			}
 			/*
@@ -200,6 +205,6 @@ __cxa_finalize(void *dso)
 	if (dso == NULL)
 		_MUTEX_DESTROY(&atexit_mutex);
 
-	if (has_phdr && &__pthread_cxa_finalize != NULL)
+	if (has_phdr && !global_exit && &__pthread_cxa_finalize != NULL)
 		__pthread_cxa_finalize(&phdr_info);
 }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 834 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/freebsd-ports/attachments/20131206/91210746/attachment.sig>


More information about the freebsd-ports mailing list