Make sure rust's fish_setlocale() inits global C++ variables

We can't just call the Rust version of `fish_setlocale()` without also either
calling the C++ version of `fish_setlocale()` or removing all `src/complete.cpp`
variables that are initialized and aliasing them to their new rust counterparts.

Since we're not interested in keeping the C++ code around, just call the C++
version of the function via ffi until we don't have *any* C++ code referencing
`src/common.h` at all.

Note that *not* doing this and then calling the rust version of
`fish_setlocale()` instead of the C++ version will cause errant behavior and
random segfaults as the C++ code will try to read and use uninitialized values
(including uninitialized pointers) that have only had their rust counterparts
init.
This commit is contained in:
Mahmoud Al-Qudsi 2023-05-16 17:22:16 -05:00
parent c71342b933
commit 6bb2725f67
2 changed files with 19 additions and 1 deletions

View file

@ -1345,7 +1345,7 @@ pub type FilenameRef = Rc<WString>;
/// This function should be called after calling `setlocale()` to perform fish specific locale
/// initialization.
#[widestrs]
fn fish_setlocale() {
pub fn fish_setlocale() {
// Use various Unicode symbols if they can be encoded using the current locale, else a simple
// ASCII char alternative. All of the can_be_encoded() invocations should return the same
// true/false value since the code points are in the BMP but we're going to be paranoid. This
@ -1395,6 +1395,15 @@ fn fish_setlocale() {
);
}
PROFILING_ACTIVE.store(true);
// Until no C++ code uses the variables init in the C++ version of fish_setlocale(), we need to
// also call that one or otherwise we'll segfault trying to read those uninit values.
extern "C" {
fn fish_setlocale_ffi();
}
unsafe {
fish_setlocale_ffi();
}
}
/// Test if the character can be encoded using the current locale.

View file

@ -1572,3 +1572,12 @@ bool is_console_session() {
}();
return console_session;
}
/// Expose the C++ version of fish_setlocale as fish_setlocale_ffi so the variables we initialize
/// can be init even if the rust version of the function is called instead. This is easier than
/// declaring all those variables as extern, which I'll do in a separate PR.
extern "C" {
void fish_setlocale_ffi() {
fish_setlocale();
}
}