X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Flinux_specific.c;h=5d2924656b90c1a2b37d6be8b8ede20a60a30df1;hb=84b88ba59e2940c45bb3625bb5b2085613b8faef;hp=6e069c4253063bc3db3e3eb15ec8e7d11fd70c84;hpb=5cf8c8914099fbdd678ddb071d4f410abace65e8;p=vlc diff --git a/src/misc/linux_specific.c b/src/misc/linux_specific.c index 6e069c4253..5d2924656b 100644 --- a/src/misc/linux_specific.c +++ b/src/misc/linux_specific.c @@ -22,60 +22,96 @@ # include "config.h" #endif -#include +#include +#include + +#include #include "../libvlc.h" -#if 0 -#include -#include -#include +static const char default_path[] = PKGLIBDIR; static void set_libvlc_path (void) { - static char libvlc_path[PATH_MAX]; - - assert (strlen (LIBDIR) < sizeof (libvlc_path)); - strcpy (libvlc_path, LIBDIR); /* fail safe */ - vlc_global ()->psz_vlcpath = libvlc_path; - /* Find the path to libvlc (i.e. ourselves) */ FILE *maps = fopen ("/proc/self/maps", "rt"); if (maps == NULL) - return; + goto error; + + char *line = NULL; + size_t linelen = 0; + uintptr_t needle = (uintptr_t)set_libvlc_path; for (;;) { - char buf[5000], *dir, *end; - - if (fgets (buf, sizeof (buf), maps) == NULL) + ssize_t len = getline (&line, &linelen, maps); + if (len == -1) break; - dir = strchr (buf, '/'); + void *start, *end; + if (sscanf (line, "%p-%p", &start, &end) < 2) + continue; + if (needle < (uintptr_t)start || (uintptr_t)end <= needle) + continue; + char *dir = strchr (line, '/'); if (dir == NULL) continue; - end = strrchr (dir, '/'); + char *file = strrchr (line, '/'); if (end == NULL) continue; - if (strncmp (end + 1, "libvlc.so.", 10)) - continue; - - *end = '\0'; - printf ("libvlc at %s\n", dir); - if (strlen (dir) < sizeof (libvlc_path)) - strcpy (libvlc_path, dir); + *file = '\0'; + if (asprintf (&psz_vlcpath, "%s/"PACKAGE, dir) == -1) + goto error; break; } - + free (line); fclose (maps); + return; + +error: + psz_vlcpath = (char *)default_path; /* default, cannot fail */ } + +static void unset_libvlc_path (void) +{ + if (psz_vlcpath != default_path) + free (psz_vlcpath); +} + +static struct +{ + vlc_mutex_t lock; + unsigned refs; +} once = { VLC_STATIC_MUTEX, 0 }; + +#ifdef __GLIBC__ +# include +# include #endif void system_Init (libvlc_int_t *libvlc, int *argc, const char *argv[]) { -#if 0 - static pthread_once_t once = PTHREAD_ONCE_INIT; - pthread_once (&once, set_libvlc_path); +#ifdef __GLIBC__ + const char *glcv = gnu_get_libc_version (); + + /* gettext in glibc 2.5-2.7 is not thread-safe. LibVLC keeps crashing, + * especially in sterror_r(). Even if we have NLS disabled, the calling + * process might have called setlocale(). */ + if (strverscmp (glcv, "2.5") >= 0 && strverscmp (glcv, "2.8") < 0) + { + fputs ("LibVLC has detected an unusable buggy GNU/libc version.\n" + "Please update to version 2.8 or newer.\n", stderr); + fflush (stderr); +#ifndef DISABLE_BUGGY_GLIBC_CHECK + abort (); #endif + } +#endif + + vlc_mutex_lock (&once.lock); + if (once.refs++ == 0) + set_libvlc_path (); + vlc_mutex_unlock (&once.lock); + (void)libvlc; (void)argc; (void)argv; } @@ -86,6 +122,10 @@ void system_Configure (libvlc_int_t *libvlc, int *argc, const char *argv[]) void system_End (libvlc_int_t *libvlc) { + vlc_mutex_lock (&once.lock); + if (--once.refs == 0) + unset_libvlc_path (); + vlc_mutex_unlock (&once.lock); + (void)libvlc; } -