This is the mail archive of the
glibc-linux@ricardo.ecn.wfu.edu
mailing list for the glibc project.
Re: Intercepting calls to pthread_create (or any pthreads function)
- To: glibc-linux at ricardo dot ecn dot wfu dot edu, agold at bga dot com
- Subject: Re: Intercepting calls to pthread_create (or any pthreads function)
- From: "Philip J. Mucci" <mucci at cs dot utk dot edu>
- Date: Wed, 07 Mar 2001 16:41:02 -0800
- Organization: ICL/UTK - See http://icl.cs.utk.edu
- References: <3AA469E3.9050905@cs.utk.edu> <3AA5755A.3CE00574@bga.com>
- Reply-To: glibc-linux at ricardo dot ecn dot wfu dot edu
Hi Arthur,
Thanks for the info. I was excited to try this, as I've been trying to
get this to work forever, But I get a segfault 3 out of 4 times. Any
ideas? Did I botch the link order?
Thanks again for any help,
-Phil
$ gcc -Wall -fpic -shared -ggdb dlpthr.c -pthread -ldl -o libpthr.so
$ gcc -Wall -ggdb test1.c -pthreads
$ setenv LD_PRELOAD `pwd`/libpthr.so
[mucci@localhost ~/development]$ ./a.out
PID 2155 TID 1026
User thread 1026
User thread 1024
PID 2156 TID 2051
Segmentation fault
[mucci@localhost ~/development]$ ./a.out
PID 2163 TID 1026
User thread 1026
PID 2164 TID 2051
User thread 2051
User thread 1024
"Arthur H. Gold" wrote:
>
> Not exactly; but it's still not the optimal solution.
> Since `libpthread.so' is already linked into your program,
> instead of doing a dlopen/dlsym just do a `dlsym( RTLD_NEXT,
> "pthread_create" )' to obtain the pointer to the `real'
> pthread_create.
>
> There's also the issue of how you compile/link the .so you
> plan to use via LD_PRELOAD. For example, you should not have
> to `#define _REENTRANT' in your code at all -- you should
> link in linuxthreads by using the `-pthread' option, as it
> makes sure that `_REENTRANT' is defined, as well as making
> sure that the library shows up in the link order at the
> right place.
>
> [cc:-ed to OP]
>
> HTH,
> --ag
>
> [BTW -- I've done extensive LD_PRELOAD stuff; feel free to
> contact me directly --ag]
> >
> > So my question is, how can I intercept a call and then call the real
> > version? Is it possible? The real reason I need to do this is to enable
> > a profiling timer in the child thread.
> >
> > Thanks,
> >
> > #define _REENTRANT
> > #include <pthread.h>
> > #include <stdio.h>
> > #include <dlfcn.h>
> >
> > typedef struct {
> > void *arg;
> > void *(*fn)(void *);
> > } real_args;
> >
> > void *create_head(void *arg)
> > {
> > real_args *a = arg;
> >
> > fprintf(stderr,"PID %d TID %d\n",
> > getpid(),(int)pthread_self());
> > return(a->fn(a->arg));
> > }
> >
> > int pthread_create(pthread_t *thread,
> > __const pthread_attr_t *attr,
> > void * (*start_routine)(void *), void * arg)
> > {
> > real_args args;
> > static void *handle = NULL;
> > static int (*real_pthread_create)(pthread_t *,
> > __const pthread_attr_t *,
> > void * (*)(void *), void *) = NULL;
> >
> > args.arg = arg;
> > args.fn = start_routine;
> >
> > if (handle == NULL)
> > {
> > handle = dlopen("/usr/lib/libpthread.so",RTLD_LAZY);
> > if (handle == NULL)
> > {
> > fprintf(stderr,"dlopen(%s) failed\n","/usr/lib/libpthread.so");
> > exit(1);
> > }
> > real_pthread_create = dlsym(handle,"pthread_create");
> > if (handle == NULL)
> > {
> > fprintf(stderr,"dlsym(%s) failed\n","pthread_create");
> > exit(1);
> > }
> > }
> > return(real_pthread_create(thread,attr,create_head,&args));
> > }
>
> --
> Artie Gold, Austin, TX (finger the cs.utexas.edu account
> for more info)
> mailto:agold@bga.com or mailto:agold@cs.utexas.edu
> --
> Verbing weirds language.
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
typedef struct {
void *arg;
void *(*fn)(void *);
} real_args;
void *create_head(void *arg)
{
real_args *a = arg;
fprintf(stderr,"PID %d TID %d\n",
getpid(),(int)pthread_self());
return(a->fn(a->arg));
}
int pthread_create(pthread_t *thread,
__const pthread_attr_t *attr,
void * (*start_routine)(void *), void * arg)
{
real_args args;
#if 0
static void *handle = NULL;
#endif
static int (*real_pthread_create)(pthread_t *,
__const pthread_attr_t *,
void * (*)(void *), void *) = NULL;
args.arg = arg;
args.fn = start_routine;
if (real_pthread_create == NULL)
{
#if 0
handle = dlopen("/usr/lib/libpthread.so",RTLD_LAZY);
if (handle == NULL)
{
fprintf(stderr,"dlopen(%s) failed\n","/usr/lib/libpthread.so");
exit(1);
}
#endif
real_pthread_create = dlsym(RTLD_NEXT,"pthread_create");
if (real_pthread_create == NULL)
{
fprintf(stderr,"dlsym(%s) failed\n","pthread_create");
exit(1);
}
}
return(real_pthread_create(thread,attr,create_head,&args));
}
#include <pthread.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <assert.h>
#include <unistd.h>
#include <sys/unistd.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <sched.h>
#include "sigstuff.h"
void *thr(void *t)
{
int i = 1000000000;
fprintf(stderr,"User thread %lu\n",pthread_self());
while(i)
i--;
return(NULL);
}
int main(int argc, char **argv)
{
pthread_t t1, t2;
// start_timer(100);
assert(pthread_create(&t1,NULL,thr,NULL) == 0);
assert(pthread_create(&t2,NULL,thr,NULL) == 0);
thr(NULL);
exit(0);
}