Attachment "tcl9.1.0-locale-init-lock.patch" to
ticket [c35e347c6f]
added by
gustafn3
2026-10-07 09:22:20.
--- a/unix/tclUnixInit.c
+++ b/unix/tclUnixInit.c
@@ -584,25 +584,43 @@
*/
#ifdef HAVE_LANGINFO
- if (
+ {
+ Tcl_DString ds;
+ int haveLocale;
+
+ Tcl_DStringInit(&ds);
+
+ /*
+ * setlocale() changes process-global state and need not be thread-safe.
+ * Use the initialization lock, which also protects the initial locale
+ * setup in Tcl_InitSubsystems(). Copy the codeset while holding the
+ * lock, since nl_langinfo() can return storage owned by libc.
+ */
+
+ TclpInitLock();
+ haveLocale =
#ifdef WEAK_IMPORT_NL_LANGINFO
- nl_langinfo != NULL &&
+ nl_langinfo != NULL &&
#endif
- setlocale(LC_CTYPE, "") != NULL) {
- Tcl_DString ds;
+ setlocale(LC_CTYPE, "") != NULL;
+ if (haveLocale) {
+ Tcl_DStringAppend(&ds, nl_langinfo(CODESET), TCL_INDEX_NONE);
+ }
+ TclpInitUnlock();
/*
- * Use a DString so we can modify case.
+ * Resolve the copied encoding name after releasing the locale lock.
*/
- Tcl_DStringInit(&ds);
- encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), TCL_INDEX_NONE);
- Tcl_UtfToLower(Tcl_DStringValue(&ds));
- knownEncoding = SearchKnownEncodings(encoding);
- if (knownEncoding != NULL) {
- Tcl_DStringAppend(bufPtr, knownEncoding, TCL_INDEX_NONE);
- } else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
- Tcl_DStringAppend(bufPtr, encoding, TCL_INDEX_NONE);
+ if (haveLocale) {
+ encoding = Tcl_DStringValue(&ds);
+ Tcl_UtfToLower(Tcl_DStringValue(&ds));
+ knownEncoding = SearchKnownEncodings(encoding);
+ if (knownEncoding != NULL) {
+ Tcl_DStringAppend(bufPtr, knownEncoding, TCL_INDEX_NONE);
+ } else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
+ Tcl_DStringAppend(bufPtr, encoding, TCL_INDEX_NONE);
+ }
}
Tcl_DStringFree(&ds);
if (Tcl_DStringLength(bufPtr)) {