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.
This commit is contained in:
Mahmoud Al-Qudsi 2024-01-13 13:50:31 -06:00
parent a138d74688
commit 195852b562
3 changed files with 7 additions and 7 deletions

View file

@ -678,6 +678,8 @@ fn init_curses(vars: &EnvStack) {
/// Initialize the locale subsystem /// Initialize the locale subsystem
fn init_locale(vars: &EnvStack) { fn init_locale(vars: &EnvStack) {
let _guard = crate::locale::LOCALE_LOCK.lock().unwrap();
#[rustfmt::skip] #[rustfmt::skip]
const UTF8_LOCALES: &[&str] = &[ const UTF8_LOCALES: &[&str] = &[
"C.UTF-8", "en_US.UTF-8", "en_GB.UTF-8", "de_DE.UTF-8", "C.utf8", "UTF-8", "C.UTF-8", "en_US.UTF-8", "en_GB.UTF-8", "de_DE.UTF-8", "C.utf8", "UTF-8",

View file

@ -2,6 +2,9 @@
pub use printf_compat::locale::{Locale, C_LOCALE}; pub use printf_compat::locale::{Locale, C_LOCALE};
use std::sync::Mutex; 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. /// It's CHAR_MAX.
const CHAR_MAX: libc::c_char = libc::c_char::max_value(); const CHAR_MAX: libc::c_char = libc::c_char::max_value();
@ -102,7 +105,7 @@ unsafe fn read_locale() -> Option<Locale> {
unsafe fn read_locale() -> Option<Locale> { unsafe fn read_locale() -> Option<Locale> {
// Bleh, we have to go through localeconv, which races with setlocale. // Bleh, we have to go through localeconv, which races with setlocale.
// TODO: There has to be a better way to do this. // 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 empty: [libc::c_char; 1] = [0];
const c_loc_str: [libc::c_char; 2] = [b'C' as libc::c_char, 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<Locale> {
// Current numeric locale. // Current numeric locale.
static NUMERIC_LOCALE: Mutex<Option<Locale>> = Mutex::new(None); static NUMERIC_LOCALE: Mutex<Option<Locale>> = 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 { pub fn get_numeric_locale() -> Locale {
let mut locale = NUMERIC_LOCALE.lock().unwrap(); let mut locale = NUMERIC_LOCALE.lock().unwrap();
if locale.is_none() { if locale.is_none() {

View file

@ -2,16 +2,15 @@ use crate::common::{
escape_string, str2wcstring, unescape_string, wcs2string, EscapeFlags, EscapeStringStyle, escape_string, str2wcstring, unescape_string, wcs2string, EscapeFlags, EscapeStringStyle,
UnescapeStringStyle, ENCODE_DIRECT_BASE, ENCODE_DIRECT_END, UnescapeStringStyle, ENCODE_DIRECT_BASE, ENCODE_DIRECT_END,
}; };
use crate::locale::LOCALE_LOCK;
use crate::wchar::{wstr, WString, L}; use crate::wchar::{wstr, WString, L};
use crate::wutil::encoding::{wcrtomb, zero_mbstate, AT_LEAST_MB_LEN_MAX}; use crate::wutil::encoding::{wcrtomb, zero_mbstate, AT_LEAST_MB_LEN_MAX};
use rand::{Rng, RngCore}; use rand::{Rng, RngCore};
use rand_pcg::Pcg64Mcg; use rand_pcg::Pcg64Mcg;
use std::sync::Mutex;
/// wcs2string is locale-dependent, so ensure we have a multibyte locale /// wcs2string is locale-dependent, so ensure we have a multibyte locale
/// before using it in a test. /// before using it in a test.
fn setlocale() { fn setlocale() {
static LOCALE_LOCK: Mutex<()> = Mutex::new(());
let _guard = LOCALE_LOCK.lock().unwrap(); let _guard = LOCALE_LOCK.lock().unwrap();
#[rustfmt::skip] #[rustfmt::skip]