This is the mail archive of the glibc-linux@ricardo.ecn.wfu.edu mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Intercepting calls to pthread_create (or any pthreads function)


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);
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]