X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=bin%2Foverride.c;h=b5de22d0f558b4c941937048c63ea11c75ffc0a9;hb=053f9d6ea00435633c3dcbf87041d868223c9ec7;hp=113a63844597d4f61151616d6e9ab350bdf9972d;hpb=209c152e39ae22bf3842ff81f5b829c099d3aae7;p=vlc diff --git a/bin/override.c b/bin/override.c index 113a638445..b5de22d0f5 100644 --- a/bin/override.c +++ b/bin/override.c @@ -26,18 +26,22 @@ void vlc_enable_override (void); -#if defined (__GNUC__) /* typeof and statement-expression */ \ +#if defined (__GNUC__) \ && (defined (__ELF__) && !defined (__sun__)) /* Solaris crashes on printf("%s", NULL); which is legal, but annoying. */ #include #include #include +#include #include #include #ifdef HAVE_EXECINFO_H # include #endif +#ifdef NDEBUG +# undef HAVE_BACKTRACE +#endif static bool override = false; @@ -56,7 +60,7 @@ static void vlogbug (const char *level, const char *func, const char *fmt, va_list ap) { #ifdef HAVE_BACKTRACE - const size_t framec = 8; + const size_t framec = 4; void *framev[framec]; backtrace (framev, framec); @@ -86,15 +90,31 @@ static void *getsym (const char *name) void *sym = dlsym (RTLD_NEXT, name); if (sym == NULL) { - fprintf (stderr, "Cannot resolve symbol %s!\n", name); + fprintf (stderr, "Cannot resolve symbol %s: %s\n", name, + dlerror ()); abort (); } return sym; } #define LOG(level, ...) logbug(level, __func__, __VA_ARGS__) +/* Evil non-standard GNU C macro ;) + * typeof keyword, + * statement-expression, + * nested function... + */ #define CALL(func, ...) \ - ({ typeof (func) *sym = getsym ( # func); sym (__VA_ARGS__); }) +({ \ + static typeof (func) *sym = NULL; \ + static pthread_once_t once = PTHREAD_ONCE_INIT; \ + auto void getsym_once (void); \ + void getsym_once (void) \ + { \ + sym = getsym ( # func); \ + } \ + pthread_once (&once, getsym_once); \ + sym (__VA_ARGS__); \ +}) /*** Environment *** @@ -144,24 +164,28 @@ int unsetenv (const char *name) * preserve reproducibility of the number sequence (which usually does not * matter). **/ -static pthread_mutex_t prng_lock = PTHREAD_MUTEX_INITIALIZER; +static struct +{ + pthread_mutex_t lock; + unsigned int seed; +} prng = { PTHREAD_MUTEX_INITIALIZER, 0, }; void srand (unsigned int seed) { - pthread_mutex_lock (&prng_lock); + pthread_mutex_lock (&prng.lock); LOG("Warning", "%d", seed); - CALL(srand, seed); - pthread_mutex_unlock (&prng_lock); + prng.seed = seed; + pthread_mutex_unlock (&prng.lock); } int rand (void) { int ret; - pthread_mutex_lock (&prng_lock); + pthread_mutex_lock (&prng.lock); LOG("Warning", ""); - ret = CALL(rand); - pthread_mutex_unlock (&prng_lock); + ret = rand_r (&prng.seed); + pthread_mutex_unlock (&prng.lock); return ret; } @@ -169,29 +193,88 @@ int rand (void) /** Signals **/ #include +static bool blocked_signal (int num) +{ + switch (num) + { + case SIGINT: + case SIGHUP: + case SIGQUIT: + case SIGTERM: + case SIGPIPE: + case SIGCHLD: + return true; + } + return false; +} + void (*signal (int signum, void (*handler) (int))) (int) { if (override) { - const char *msg = "Error"; - - if ((signum == SIGPIPE && handler == SIG_IGN) - || (signum != SIGPIPE && handler == SIG_DFL)) - /* Same settings we already use */ - msg = "Warning"; - LOG(msg, "%d, %p", signum, handler); + if (handler != SIG_IGN && handler != SIG_DFL) + goto error; + if (!blocked_signal (signum)) + goto error; + /* For our blocked signals, the handler won't matter much... */ + if (handler == SIG_DFL) + LOG("Warning", "%d, SIG_DFL", signum, handler); } return CALL(signal, signum, handler); +error: + LOG("Blocked", "%d, %p", signum, handler); + return SIG_DFL; } int sigaction (int signum, const struct sigaction *act, struct sigaction *old) { - if (act != NULL) - LOG("Error", "%d, %p, %p", signum, act, old); + if (override && act != NULL) + { + if ((act->sa_flags & SA_SIGINFO) + || (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL)) + goto error; + if (act->sa_handler == SIG_DFL) + LOG("Warning", "%d, %p, SIG_DFL", signum, act); + } return CALL(sigaction, signum, act, old); +error: + LOG("Blocked", "%d, %p, %p", signum, act, old); + return -1; +} + + +/*** Locales *** + * setlocale() is not thread-safe and has a tendency to crash other threads as + * quite many libc and libintl calls depend on the locale. + * Use uselocale() instead for thread-safety. + */ +#include + +char *setlocale (int cat, const char *locale) +{ + if (override && locale != NULL) + { + LOG("Blocked", "%d, \"%s\"", cat, locale); + return NULL; + } + return CALL(setlocale, cat, locale); } +/* strerror() is not thread-safe in theory (POSIX), nor in practice (glibc). + * This caused quite nasty crashes in the history of VLC/Linux. */ +char *strerror (int val) +{ + if (override) + { + static const char msg[] = + "Error message unavailable (use strerror_r instead of strerror)!"; + LOG("Blocked", "%d", val); + return (char *)msg; + } + return CALL(strerror, val); +} + /*** Xlib ****/ #ifdef HAVE_X11_XLIB_H # include @@ -230,7 +313,7 @@ int (*XSetIOErrorHandler (int (*handler) (Display *))) (Display *) } #endif #else -static void vlc_enable_override (void) +void vlc_enable_override (void) { } #endif