From 195852b562e829d817c6e5782bd4af8522130871 Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Sat, 13 Jan 2024 13:50:31 -0600 Subject: [PATCH] Use locale::LOCALE_LOCK for all setlocale() calls I had originally created a safe `set_locale()` wrapper and clippy-disallowed `libc::setlocale()` but almost all our uses of `libc::setlocale()` are in a loop where it makes much more sense to just obtain the lock outright then call `setlocale()` repeatedly rather than lock it in the wrapper function each time. --- src/env_dispatch.rs | 2 ++ src/locale.rs | 9 ++++----- src/tests/string_escape.rs | 3 +-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/env_dispatch.rs b/src/env_dispatch.rs index b006a9c75..8b166566b 100644 --- a/src/env_dispatch.rs +++ b/src/env_dispatch.rs @@ -678,6 +678,8 @@ fn init_curses(vars: &EnvStack) { /// Initialize the locale subsystem fn init_locale(vars: &EnvStack) { + let _guard = crate::locale::LOCALE_LOCK.lock().unwrap(); + #[rustfmt::skip] const UTF8_LOCALES: &[&str] = &[ "C.UTF-8", "en_US.UTF-8", "en_GB.UTF-8", "de_DE.UTF-8", "C.utf8", "UTF-8", diff --git a/src/locale.rs b/src/locale.rs index 70415fa45..5a1f45a11 100644 --- a/src/locale.rs +++ b/src/locale.rs @@ -2,6 +2,9 @@ pub use printf_compat::locale::{Locale, C_LOCALE}; use std::sync::Mutex; +/// Lock guarding libc `setlocale()` or `localeconv()` calls to avoid races. +pub(crate) static LOCALE_LOCK: Mutex<()> = Mutex::new(()); + /// It's CHAR_MAX. const CHAR_MAX: libc::c_char = libc::c_char::max_value(); @@ -102,7 +105,7 @@ unsafe fn read_locale() -> Option { unsafe fn read_locale() -> Option { // Bleh, we have to go through localeconv, which races with setlocale. // TODO: There has to be a better way to do this. - let _guard = SETLOCALE_LOCK.lock().unwrap(); + let _guard = LOCALE_LOCK.lock().unwrap(); const empty: [libc::c_char; 1] = [0]; const c_loc_str: [libc::c_char; 2] = [b'C' as libc::c_char, 0]; @@ -122,10 +125,6 @@ unsafe fn read_locale() -> Option { // Current numeric locale. static NUMERIC_LOCALE: Mutex> = Mutex::new(None); -/// Lock guarding setlocale() calls to avoid races. -// TODO: need to grab this lock when we port setlocale() calls. -static SETLOCALE_LOCK: Mutex<()> = Mutex::new(()); - pub fn get_numeric_locale() -> Locale { let mut locale = NUMERIC_LOCALE.lock().unwrap(); if locale.is_none() { diff --git a/src/tests/string_escape.rs b/src/tests/string_escape.rs index 4b59c1931..1dc837d72 100644 --- a/src/tests/string_escape.rs +++ b/src/tests/string_escape.rs @@ -2,16 +2,15 @@ use crate::common::{ escape_string, str2wcstring, unescape_string, wcs2string, EscapeFlags, EscapeStringStyle, UnescapeStringStyle, ENCODE_DIRECT_BASE, ENCODE_DIRECT_END, }; +use crate::locale::LOCALE_LOCK; use crate::wchar::{wstr, WString, L}; use crate::wutil::encoding::{wcrtomb, zero_mbstate, AT_LEAST_MB_LEN_MAX}; use rand::{Rng, RngCore}; use rand_pcg::Pcg64Mcg; -use std::sync::Mutex; /// wcs2string is locale-dependent, so ensure we have a multibyte locale /// before using it in a test. fn setlocale() { - static LOCALE_LOCK: Mutex<()> = Mutex::new(()); let _guard = LOCALE_LOCK.lock().unwrap(); #[rustfmt::skip]