diff --git a/src/fallback.cpp b/src/fallback.cpp index d7e4e508e..8a7d6a0e2 100644 --- a/src/fallback.cpp +++ b/src/fallback.cpp @@ -390,9 +390,10 @@ int flock(int fd, int op) { #endif // HAVE_FLOCK #ifndef HAVE_WCSTOD_L -// musl doesn't feature wcstod_l, -// so we just wrap wcstod. -double wcstod_l(const wchar_t *enptr, wchar_t **endptr, locale_t loc) { +#undef wcstod_l +// For platforms without wcstod_l C extension, wrap wcstod after changing the +// thread-specific locale. +double fish_compat::wcstod_l(const wchar_t *enptr, wchar_t **endptr, locale_t loc) { char *saved_locale = strdup(setlocale(LC_NUMERIC, NULL)); // Yes, this is hardcoded to use the "C" locale. // That's the only thing we need, and uselocale(loc) broke in my testing. diff --git a/src/fallback.h b/src/fallback.h index f8b7d4977..b935c8460 100644 --- a/src/fallback.h +++ b/src/fallback.h @@ -200,5 +200,15 @@ int flock(int fd, int op); #endif #ifndef HAVE_WCSTOD_L -double wcstod_l(const wchar_t *enptr, wchar_t **endptr, locale_t loc); +// On some platforms if this is incorrectly detected and a system-defined +// defined version of `wcstod_l` exists, calling `wcstod` from our own +// `wcstod_l` can call back into `wcstod_l` causing infinite recursion. +// e.g. FreeBSD defines `wcstod(x, y)` as `wcstod_l(x, y, __get_locale())`. +// Solution: namespace our implementation to make sure there is no symbol +// duplication. +#undef wcstod_l +namespace fish_compat { + double wcstod_l(const wchar_t *enptr, wchar_t **endptr, locale_t loc); +} +#define wcstod_l(x, y, z) fish_compat::wcstod_l(x, y, z) #endif