mirror of https://github.com/mpv-player/mpv
client API: check locale, and reject anything other than "C" locale
Sigh... The C locale system is incredibly shitty, and if used, breaks basic string functions. The locale can change the decimal mark from "." to ",", which affects conversion between floats and strings: snprintf() and strtod() respect the locale decimal mark, and change behavior. (What's even better, the behavior of these functions can change asynchronously, if setlocale() is called after threads were started.) So just check the locale in the client API, and refuse to work if it's wrong. This also makes the lib print to stderr, which I consider the lesser evil in this specific situation.
This commit is contained in:
parent
9f63b9f673
commit
21322a016e
|
@ -17,6 +17,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <locale.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
|
@ -439,8 +440,23 @@ void mpv_terminate_destroy(mpv_handle *ctx)
|
||||||
pthread_join(playthread, NULL);
|
pthread_join(playthread, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We mostly care about LC_NUMERIC, and how "." vs. "," is treated,
|
||||||
|
// Other locale stuff might break too, but probably isn't too bad.
|
||||||
|
static bool check_locale(void)
|
||||||
|
{
|
||||||
|
char *name = setlocale(LC_NUMERIC, NULL);
|
||||||
|
return strcmp(name, "C") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
mpv_handle *mpv_create(void)
|
mpv_handle *mpv_create(void)
|
||||||
{
|
{
|
||||||
|
if (!check_locale()) {
|
||||||
|
// Normally, we never print anything (except if the "terminal" option
|
||||||
|
// is enabled), so this is an exception.
|
||||||
|
fprintf(stderr, "Non-C locale detected. This is not supported.\n"
|
||||||
|
"Call 'setlocale(LC_NUMERIC, \"C\");' in your code.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
struct MPContext *mpctx = mp_create();
|
struct MPContext *mpctx = mp_create();
|
||||||
mpv_handle *ctx = mp_new_client(mpctx->clients, "main");
|
mpv_handle *ctx = mp_new_client(mpctx->clients, "main");
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
|
|
Loading…
Reference in New Issue