Now that glibc 2.3 is available for those bleeding-edge folks on debian unstable, it seems that Wines compiled on 2.2 won't run on 2.3 systems. The glibc folks did warn us about this a while ago though, so here's a patch that implements their suggestion for making wine compatible with as many glibc versions as possible. Perhaps Alexandre wants to use his WINE_GET_SONAME stuff to detect the name of the libc at configure time instead of at runtime like I do, though. Log: Ove Kaaven <ovek@transgaming.com> Resolve libc symbols we need (fork and sigaction) at runtime with dlsym() so that Wine runs on newer glibc versions than what it was compiled on. Index: scheduler/pthread.c =================================================================== RCS file: /cvsroot/winex/wine/scheduler/pthread.c,v retrieving revision 1.11 diff -u -r1.11 pthread.c --- scheduler/pthread.c 25 Sep 2002 20:15:50 -0000 1.11 +++ scheduler/pthread.c 20 Oct 2002 20:28:36 -0000 @@ -18,6 +18,7 @@ #include <stdlib.h> #include <unistd.h> #include <string.h> +#include <dlfcn.h> #include "winbase.h" #include "thread.h" @@ -64,21 +65,11 @@ "\tjmp " PSTR(orig)) #endif -/* get necessary libc symbols */ -#if (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1) && defined(HAVE___LIBC_FORK) -#define LIBC_FORK __libc_fork -#define PTHREAD_FORK __fork -#define ALIAS_FORK -#else -#define LIBC_FORK __fork -#define PTHREAD_FORK fork -#endif -extern pid_t LIBC_FORK(void); - -#define LIBC_SIGACTION __sigaction -extern int LIBC_SIGACTION(int signum, - const struct sigaction *act, - struct sigaction *oldact); +static void *libc_handle = NULL; +static pid_t (*libc_fork)(void); +static int (*libc_sigaction)(int signum, + const struct sigaction *act, + struct sigaction *oldact); /* NOTE: This is a truly extremely incredibly ugly hack! * But it does seem to work... */ @@ -113,6 +104,25 @@ #define P_OUTPUT(stuff) write(2,stuff,strlen(stuff)) #endif +static void grab_libc(void) +{ + void *libc_open; + Dl_info info; + + if (libc_handle) return; + + /* to find the real name of libc, we can either detect it with configure + * and compile the name into wine, or detect it at runtime, like this */ + libc_open = dlsym(RTLD_NEXT, "fopen"); + dladdr(libc_open, &info); /* <== GNU extension */ + + /* now we can grab a libc handle */ + libc_handle = dlopen(info.dli_fname, RTLD_LAZY); + /* and thus the entry points we need */ + libc_fork = dlsym(libc_handle, "fork"); + libc_sigaction = dlsym(libc_handle, "sigaction"); +} + void __pthread_initialize(void) { } @@ -254,15 +264,16 @@ } strong_alias(__pthread_atfork, pthread_atfork); -pid_t PTHREAD_FORK(void) +pid_t __fork(void) { pid_t pid; int i; EnterCriticalSection( &atfork_section ); + grab_libc(); /* prepare handlers are called in reverse insertion order */ for (i = atfork_count - 1; i >= 0; i--) if (atfork_prepare[i]) atfork_prepare[i](); - if (!(pid = LIBC_FORK())) + if (!(pid = (*libc_fork)())) { InitializeCriticalSection( &atfork_section ); for (i = 0; i < atfork_count; i++) if (atfork_child[i]) atfork_child[i](); @@ -274,9 +285,7 @@ } return pid; } -#ifdef ALIAS_FORK -strong_alias(PTHREAD_FORK, fork); -#endif +strong_alias(__fork, fork); /***** MUTEXES *****/ @@ -657,14 +666,11 @@ /***** ANTI-OVERRIDES *****/ /* pthreads tries to override these, point them back to libc */ -#ifdef jump_alias -jump_alias(LIBC_SIGACTION, sigaction); -#else int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) { - return LIBC_SIGACTION(signum, act, oldact); + grab_libc(); + return (*libc_sigaction)(signum, act, oldact); } -#endif #endif /* __GLIBC__ */