linuxthreads.new aliases

Timo Teräs timo.teras at iki.fi
Wed Jun 17 13:52:27 UTC 2009


Hi,

It looks like the aliases in linuxthreads.new are a bit off.
If the main binary pulls in libc before libpthread, because of
some other dependent .so, you end up using the aliases from
libc and not libpthread.

This causes forward.c definitions to call themselves recursively
for the pthread_mutex_* where forward.c has strong_alias for the
internal variants. Similar loop would occur for _pthread_cleanup_*
since the libc implementation would take preference from the
libpthread one.

I fixed this for me by:
1. renaming the internal _pthread_cleanup_* to __pthread_cleanup_*
   and alias them properly
2. making the pthread_mutex_* aliases hidden. you should really
   have the hidden_strong_alias in some global header and do
   the compiler checking properly.

As a side note, I tried making the forward.c aliases weak, but
that did not fix the problem. Either there is a bug in the linker.
Or when the first dependent .so is linked in and it pulls in the
libc, the symbols that are resolved there are not looked up
from libpthread.so. Might need a bit of further investigation
if it's actually ld.so problem.

But having the strong_aliases in forward.c is definitely wrong.

- Timo

diff --git a/libpthread/linuxthreads/cancel.c b/libpthread/linuxthreads/cancel.c
index 3435680..1412b57 100644
--- a/libpthread/linuxthreads/cancel.c
+++ b/libpthread/linuxthreads/cancel.c
@@ -152,8 +152,8 @@ void pthread_testcancel(void)
     __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
 }
 
-void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer,
-			   void (*routine)(void *), void * arg)
+void __pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer,
+			    void (*routine)(void *), void * arg)
 {
   pthread_descr self = thread_self();
   buffer->__routine = routine;
@@ -163,17 +163,19 @@ void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer,
     buffer->__prev = NULL;
   THREAD_SETMEM(self, p_cleanup, buffer);
 }
+strong_alias(__pthread_cleanup_push, _pthread_cleanup_push);
 
-void _pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer,
-			  int execute)
+void __pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer,
+			   int execute)
 {
   pthread_descr self = thread_self();
   if (execute) buffer->__routine(buffer->__arg);
   THREAD_SETMEM(self, p_cleanup, buffer->__prev);
 }
+strong_alias(__pthread_cleanup_pop, _pthread_cleanup_pop);
 
-void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer,
-				 void (*routine)(void *), void * arg)
+void __pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer,
+				  void (*routine)(void *), void * arg)
 {
   pthread_descr self = thread_self();
   buffer->__routine = routine;
@@ -185,9 +187,10 @@ void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer,
   THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED);
   THREAD_SETMEM(self, p_cleanup, buffer);
 }
+strong_alias(__pthread_cleanup_push_defer, _pthread_cleanup_push_defer);
 
-void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer,
-				  int execute)
+void __pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer,
+				   int execute)
 {
   pthread_descr self = thread_self();
   if (execute) buffer->__routine(buffer->__arg);
@@ -198,6 +201,7 @@ void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer,
       THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
     __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
 }
+strong_alias(__pthread_cleanup_pop_restore, _pthread_cleanup_pop_restore);
 
 extern void __rpc_thread_destroy(void);
 void __pthread_perform_cleanup(char *currentframe)
diff --git a/libpthread/linuxthreads/forward.c b/libpthread/linuxthreads/forward.c
index f9f8ea1..385e79f 100644
--- a/libpthread/linuxthreads/forward.c
+++ b/libpthread/linuxthreads/forward.c
@@ -24,6 +24,10 @@
 /* psm: keep this before internals.h */
 /* libc_hidden_proto(exit) */
 
+#define hidden_strong_alias(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((alias (#name), \
+                                                   visibility ("hidden")));
+
 #include "internals.h"
 
 /* Pointers to the libc functions.  */
@@ -104,8 +108,7 @@ FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2),
 
 /* Use an alias to avoid warning, as pthread_exit is declared noreturn.  */
 FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS))
-strong_alias (__pthread_exit, pthread_exit)
-
+hidden_strong_alias (__pthread_exit, pthread_exit)
 
 FORWARD (pthread_getschedparam,
 	 (pthread_t target_thread, int *policy, struct sched_param *param),
@@ -120,16 +123,16 @@ FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0)
 FORWARD (pthread_mutex_init,
 	 (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr),
 	 (mutex, mutexattr), 0)
-strong_alias(pthread_mutex_init, __pthread_mutex_init)
+hidden_strong_alias(pthread_mutex_init, __pthread_mutex_init)
 
 FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0)
-strong_alias(pthread_mutex_lock, __pthread_mutex_lock)
+hidden_strong_alias(pthread_mutex_lock, __pthread_mutex_lock)
 
 FORWARD (pthread_mutex_trylock, (pthread_mutex_t *mutex), (mutex), 0)
-strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock)
+hidden_strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock)
 
 FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0)
-strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock)
+hidden_strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock)
 
 FORWARD2 (pthread_self, pthread_t, (void), (), return 0)
 
diff --git a/libpthread/linuxthreads/internals.h b/libpthread/linuxthreads/internals.h
index eb0a519..4ad6a0d 100644
--- a/libpthread/linuxthreads/internals.h
+++ b/libpthread/linuxthreads/internals.h
@@ -380,6 +380,17 @@ extern int __pthread_setschedparam (pthread_t thread, int policy,
 extern int __pthread_setcancelstate (int state, int * oldstate);
 extern int __pthread_setcanceltype (int type, int * oldtype);
 
+extern void __pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
+                                    void (*__routine) (void *),
+                                    void *__arg) __THROW;
+extern void __pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
+                                   int __execute) __THROW;
+extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
+                                          void (*__routine) (void *),
+                                          void *__arg) __THROW;
+extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
+                                           int __execute) __THROW;
+
 extern void __pthread_restart_old(pthread_descr th);
 extern void __pthread_suspend_old(pthread_descr self);
 extern int __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime);
diff --git a/libpthread/linuxthreads/pthread.c b/libpthread/linuxthreads/pthread.c
index 4d1d906..012b74b 100644
--- a/libpthread/linuxthreads/pthread.c
+++ b/libpthread/linuxthreads/pthread.c
@@ -280,10 +280,10 @@ struct pthread_functions __pthread_functions =
     .ptr_pthread_sigaction = __pthread_sigaction,
     .ptr_pthread_sigwait = __pthread_sigwait,
     .ptr_pthread_raise = __pthread_raise,
-    .ptr__pthread_cleanup_push = _pthread_cleanup_push,
-    .ptr__pthread_cleanup_push_defer = _pthread_cleanup_push_defer,
-    .ptr__pthread_cleanup_pop = _pthread_cleanup_pop,
-    .ptr__pthread_cleanup_pop_restore = _pthread_cleanup_pop_restore,
+    .ptr__pthread_cleanup_push = __pthread_cleanup_push,
+    .ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer,
+    .ptr__pthread_cleanup_pop = __pthread_cleanup_pop,
+    .ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore,
   };
 #ifdef SHARED
 # define ptr_pthread_functions &__pthread_functions


More information about the uClibc mailing list