United States-English |
|
|
HP-UX Reference > Ppthread_stubs(5)HP-UX 11i Version 3: February 2007 |
|
NAMEpthread_stubs — list of pthread calls for which the stubs are provided in the C library DESCRIPTIONThe libc shared libraries in libc cumulative patches, PHCO_22923 (11.00) and PHCO_23772 (11.11) onwards, contain stubs for the pthread functions in libpthread and libcma. The stubs allow non-threaded applications to dynamically load thread-safe libraries successfully, so that the pthread symbols are resolved. Applications that resolve pthread/cma calls to the stub must be built without -lpthread or -lcma on the link line. Stubs provided in libc do not have any functionality, these are dummy functions returning zero, except the pthread_getspecific(3T) family of APIs, which have full functionality implemented in the stubs. The pthread calls to any of the stub functions below return zero. pthread_atfork(3T) pthread_attr_destroy(3T) pthread_attr_getdetachstate(3T) pthread_attr_getguardsize(3T) pthread_attr_getinheritsched(3T) pthread_attr_getschedparam(3T) pthread_attr_getschedpolicy(3T) pthread_attr_getscope(3T) pthread_attr_getstackaddr(3T) pthread_attr_getstacksize(3T) pthread_attr_setdetachstate(3T) pthread_attr_setguardsize(3T) pthread_attr_setinheritsched(3T) pthread_attr_setschedparam(3T) pthread_attr_setschedpolicy(3T) pthread_attr_setscope(3T) pthread_attr_setstackaddr(3T) pthread_attr_setstacksize(3T) pthread_cancel(3T) pthread_cond_broadcast(3T) pthread_cond_destroy(3T) pthread_cond_init(3T) pthread_cond_signal(3T) pthread_cond_timedwait(3T) pthread_cond_wait(3T) pthread_condattr_destroy(3T) pthread_condattr_getpshared(3T) pthread_condattr_init(3T) pthread_condattr_setpshared(3T) pthread_continue(3T) pthread_detach(3T) pthread_getconcurrency(3T) pthread_getschedparam(3T) pthread_join(3T) pthread_kill(3T) pthread_mutex_destroy(3T) pthread_mutex_getprioceiling(3T) pthread_mutex_init(3T) pthread_mutex_lock(3T) pthread_mutex_setprioceiling(3T) pthread_mutex_trylock(3T) pthread_mutex_unlock(3T) pthread_mutexattr_destroy(3T) pthread_mutexattr_getprioceiling(3T) pthread_mutexattr_getprotocol(3T) pthread_mutexattr_getpshared(3T) pthread_mutexattr_gettype(3T) pthread_mutexattr_init(3T) pthread_mutexattr_setprioceiling(3T) pthread_mutexattr_setprotocol(3T) pthread_mutexattr_setpshared(3T) pthread_mutexattr_settype(3T) pthread_once(3T) pthread_rwlock_destroy(3T) pthread_rwlock_init(3T) pthread_rwlock_rdlock(3T) pthread_rwlock_tryrdlock(3T) pthread_rwlock_trywrlock(3T) pthread_rwlock_unlock(3T) pthread_rwlock_wrlock(3T) pthread_rwlockattr_destroy(3T) pthread_rwlockattr_getpshared(3T) pthread_rwlockattr_init(3T) pthread_rwlockattr_setpshared(3T) pthread_self(3T) pthread_setcancelstate(3T) pthread_setcanceltype(3T) pthread_setconcurrency(3T) pthread_setschedparam(3T) pthread_sigmask(3T) pthread_suspend(3T) pthread_testcancel(3T) The stubs for the following pthread calls have full functionality. Refer to pthread(3T) for more details. pthread_key_create(3T) pthread_getspecific(3T) pthread_setspecific(3T) pthread_key_delete(3T) pthread_exit(3T) Calls to the stubs listed below, pthread_self(3T) always returns 1. pthread_equal(arg1,arg2) returns (arg1==arg2). pthread_create(3T) and pthread_attr_init(3T) return ENOSYS. The above mentioned stubs are provided in libc because on HP-UX if a non-threaded application links to a thread-safe library, calls to thread-safe routines from the application fail at run time due to unresolved symbols of the form of pthread_*. To resolve these symbols it is necessary to link the non-threaded application to a threads library (libpthread or libcma). However, linking to a threads library forces the application to use thread-safe features even if it creates no threads, resulting in a subsequent loss of performance. To overcome the above problem, stubs for POSIX.1c APIs have been provided in the C library. Providing stubs for POSIX.1c API's in the HP-UX C language library have two direct effects for non-threaded applications:
Link Order ProblemsAn application may inadvertently pick up the stubs present in libc when it intended to use the real pthread APIs, or cma APIs, due to link order issues. An application that needs cma behavior must link to libcma and must do so in the supported link order, i.e. the link line should only be shared and should not contain -lc before -lcma. As long as this condition is met, the correct cma functions will be referenced. Similarly, a multithreaded application that needs pthread library behavior must link to libpthread and must do so in a supported link order, and only use shared libc and libpthread. EXAMPLESBelow are examples of potential link order problems. Example 1An application or any library linked, that requires pthread/cma calls to resolve to the pthread stubs in libc must be built without -lpthread or -lcma on the link line. If -lc is specified before -lpthread or -lcma on the link line, pthread/cma calls resolve to pthread stubs in libc. This may lead to problems as given in the examples below: $ cat thread.c #include <pthread.h> #include <stdio.h> void *thread_nothing(void *p) { printf("Success\n"); } int main() { int err; pthread_t thrid; err = pthread_create(&thrid, (pthread_attr_t *) NULL, thread_nothing, (void *) NULL); sleep(1); if (err) { printf("Error\n"); return err; } } $ cc thread.c -lc -lpthread $ a.out Error $ chatr a.out a.out: shared executable shared library dynamic path search: SHLIB_PATH disabled second embedded path disabled first Not Defined shared library list: dynamic /usr/lib/libc.2 <- libc before libpthread dynamic /usr/lib/libpthread.1 shared library binding: deferred global hash table disabled ... Solution for Example 1For threaded applications, run the executable with environment variable LD_PRELOAD set to the libpthread library or link the executable with -lpthread: $ LD_PRELOAD="/usr/lib/libpthread.1" a.out Success $ cc thread.c -lpthread $ a.out Success $ chatr a.out a.out: shared executable shared library dynamic path search: SHLIB_PATH disabled second embedded path disabled first Not Defined shared library list: dynamic /usr/lib/libpthread.1 dynamic /usr/lib/libc.2 shared library binding: deferred global hash table disabled ... Example 2Specifying -lc before -lpthread in threaded applications can cause run-time problems like the following because the pthread calls get resolved to stubs in libc rather than the functions in pthread library.
because the pthread_mutex_lock stub returns zero. $ cat a.c #include <stdio.h> #include <dl.h> extern int errno; main() { shl_load("lib_not_found", BIND_DEFERRED, 0); printf("Error %d, %s\n", errno, strerror(errno)); } $ cc a.c -lc -lpthread $ a.out Error 22, Invalid argument $ LD_PRELOAD=/usr/lib/libpthread.1 ./a.out Error 2, No such file or directory $ cat b.c #include <stdio.h> #include <dlfcn.h> void* handle; extern int errno; main() { handle = dlopen("lib_not_found", RTLD_LAZY); printf("Error %d, %s\n", errno, strerror(errno)); if (handle == NULL) { printf("Error: %s\n",dlerror()); } } $ cc b.c -lc -lpthread $ a.out Error 22, Invalid argument Error: $ ./a.out $ LD_PRELOAD=/usr/lib/libpthread.1 Error 0, Error 0 Error: Can't open shared library: lib_not_found Due to the problems mentioned above, -lc should never be specified in the build command of an executable or shared library. By default, the compiler drivers (cc, aCC, f90) automatically pass -lc to the linker at the end of the link line of the executables. To see if a shared library was built with -lc, look at the shared library list in the chatr output (see chatr(1)), or list the dependent libraries with ldd (see ldd(1)): $ cc +z -c lib1.c $ ld -b -o lib1.sl lib1.o -lc $ ldd lib1.sl /usr/lib/libc.2 => /usr/lib/libc.2 /usr/lib/libdld.2 => /usr/lib/libdld.2 /usr/lib/libc.2 => /usr/lib/libc.2 $ cc +DA2.0W +z -c lib1.c $ ld -b -o lib1.sl lib1.o -lc $ ldd lib1.sl libc.2 => /lib/pa20_64/libc.2 libdl.1 => /usr/lib/pa20_64/libdl.1 To see the order in which dependent shared libraries will be loaded at run-time (order is only valid in 64-bit mode), use the ldd command on the executable (ldd in 32-bit mode displays the order in which libraries are loaded in reverse order): $ cc +DA2.0W thread.c -lpthread $ ldd a.out libpthread.1 => /usr/lib/pa20_64/libpthread.1 libc.2 => /usr/lib/pa20_64/libc.2 libdl.1 => /usr/lib/pa20_64/libdl.1 $ cc +DA2.0W thread.c -lc -lpthread $ ldd a.out libc.2 => /usr/lib/pa20_64/libc.2 libpthread.1 => /usr/lib/pa20_64/libpthread.1 libdl.1 => /usr/lib/pa20_64/libdl.1 $ cc +DA2.0W thread.c -lpthread -lc $ ldd a.out libpthread.1 => /usr/lib/pa20_64/libpthread.1 libc.2 => /usr/lib/pa20_64/libc.2 libdl.1 => /usr/lib/pa20_64/libdl.1 Recommendations:
Example 3 (64-bit)If a 64-bit shared library is built with -lpthread but the executable is not, libc is loaded before libpthread (due to breadth-first searching), and the pthread calls are resolved to the pthread stubs in libc. At run-time, after the a.out is loaded, the dependencies of a.out are loaded in breadth-first order: libc is loaded as a dependent of a.out before libpthread is loaded as a dependent of libc.2. The dependency list of the first case is: a.out / / \ lib1 lib2 libc | | libc libpthread Therefore the load graph is constructed as: lib1.sl --> lib2.sl -->libc.2 --> libpthread.1 This is the desired behavior for non-threaded applications, but causes threaded applications (that use either libpthread or libcma) to fail. lib1.sl specifies -lc, lib2.sl specifies -lpthread and no -lpthread on a.out. $ cc -c +z +DA2.0W lib1.c lib2.c lib1.c: lib2.c: $ ld -b -o lib1.sl -lc lib1.o $ ld -b -o lib2.sl -lpthread lib2.o $ cc +DA2.0W thread.c -L. -l1 -l2 $ a.out Error $ ldd a.out lib1.sl => ./lib1.sl lib2.sl => ./lib2.sl libc.2 => /usr/lib/pa20_64/libc.2 libc.2 => /lib/pa20_64/libc.2 libpthread.1 => /lib/pa20_64/libpthread.1 libdl.1 => /usr/lib/pa20_64/libdl.1 lib2.sl specifies -lpthread and no -lpthread on a.out. $ ld -b -o lib1.sl lib1.o $ ld -b -o lib2.sl -lpthread lib2.o $ cc +DA2.0W thread.c -L. -l1 -l2 $ a.out Error $ ldd a.out lib1.sl => ./lib1.sl lib2.sl => ./lib2.sl libc.2 => /usr/lib/pa20_64/libc.2 libpthread.1 => /lib/pa20_64/libpthread.1 libdl.1 => /usr/lib/pa20_64/libdl.1 The same problem will occur if libcma is listed as a dependent library of a shared library, and you would need to link the executable with -lcma. Recommendation for Example 3For threaded applications, run the executable with LD_PRELOAD set to the libpthread library or link the executable with -lpthread: Use LD_PRELOAD to load libpthread first $ ld -b -o lib1.sl lib1.o $ ld -b -o lib2.sl -lpthread lib2.o $ cc +DA2.0W thread.c -L. -l1 -l2 $ a.out Error $ ldd a.out lib1.sl => ./lib1.sl lib2.sl => ./lib2.sl libc.2 => /usr/lib/pa20_64/libc.2 libpthread.1 => /lib/pa20_64/libpthread.1 libdl.1 => /usr/lib/pa20_64/libdl.1 $ LD_PRELOAD="/lib/pa20_64/libpthread.1" a.out Success a.out correctly lists -lpthread for a threaded application. $ ld -b -o lib1.sl lib1.o $ ld -b -o lib2.sl -lpthread lib2.o $ cc +DA2.0W thread.c -L. -l1 -l2 -lpthread $ a.out Success $ ldd a.out lib1.sl => ./lib1.sl lib2.sl => ./lib2.sl libpthread.1 => /usr/lib/pa20_64/libpthread.1 libc.2 => /usr/lib/pa20_64/libc.2 libpthread.1 => /lib/pa20_64/libpthread.1 libdl.1 => /usr/lib/pa20_64/libdl.1 Example 4 (archived libc)If the link line of your shared library contains -lc to explicitly link in libc, remove -lc. Otherwise, shared libraries may be referencing libc.2 while the a.out may refer to older (archived) libc version. Thus the application will actually be using two different versions of libc and possibly mixing the code. This may cause compatibility problems. Basically, an application or library should never directly link against libc. All programs need to be linked against libc (which the compiler does automatically), so a shared library will always have the interfaces it needs to execute properly without needing to specify -lc on the link line. |
Printable version | ||
|