浏览代码

Fix locale handling (again)

C locale handling is completely broken. It globally affects all of the
process, and changes semantics of float parsing/formatting. It should
not be used. Unfortunately, C++ code tends to set locales to user
settings anyway for incomprehensible reasons (Qt and Chromium within
QtWebengine). This breaks at least mpv's video renderer, which formats
floats to strings when generating OpenGL shaders. It also could subtly
break other code, including ffmpeg.

The setlocale() calls in our main function were supposed to force locale
string handling to C. But this seems to have regressed with newer Qt
releases, and locale is reset at a later point again.

Do a brutal but effective workaround and set the local environment to C.
These environment variables are used by setlocale(). Glibc at least will
typically check LC_ALL first and then LC_NUMERIC, so we have to set them
both.

This is a hack, but nothing compared to the immeasurable brokenness of
the library code that sets the locale unconditionally.
Vincent Lang 8 年之前
父节点
当前提交
e89ecfd742
共有 1 个文件被更改,包括 7 次插入10 次删除
  1. 7 10
      src/main.cpp

+ 7 - 10
src/main.cpp

@@ -101,6 +101,13 @@ int main(int argc, char *argv[])
     qputenv("QT_LOGGING_RULES", "qt.network.ssl.warning=false");
 #endif
 
+    // Qt calls setlocale(LC_ALL, "") in a bunch of places, which breaks
+    // float/string processing in mpv and ffmpeg.
+#ifdef Q_OS_UNIX
+    qputenv("LC_ALL", "C");
+    qputenv("LC_NUMERIC", "C");
+#endif
+
     detectOpenGLEarly();
 
     preinitQt();
@@ -146,10 +153,6 @@ int main(int argc, char *argv[])
       return 0;
     }
 
-#ifdef Q_OS_UNIX
-    setlocale(LC_NUMERIC, "C");
-#endif
-
     detectOpenGLLate();
 
 #ifdef Q_OS_WIN32
@@ -169,12 +172,6 @@ int main(int argc, char *argv[])
 
     QtWebEngine::initialize();
 
-    // Qt and QWebEngineProfile set the locale, which breaks parsing and
-    // formatting float numbers in a few countries.
-#ifdef Q_OS_UNIX
-    setlocale(LC_NUMERIC, "C");
-#endif
-
     // start our helper
     HelperLauncher::Get().connectToHelper();