From 3301977e4ef340a6f1aa00c860dacfc636592a53 Mon Sep 17 00:00:00 2001
From: Anton Fetisov <a.fetisov@picodata.io>
Date: Thu, 6 Feb 2025 15:42:27 +0300
Subject: [PATCH] refactor: change static mut PICO_SERVICE_PASSWORD to a Rc in
 thread local

---
 src/pico_service.rs  | 29 +++++++++++++++--------------
 src/rpc/mod.rs       |  2 +-
 src/schema.rs        |  2 +-
 src/traft/network.rs |  2 +-
 4 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/src/pico_service.rs b/src/pico_service.rs
index 5dc1c11575..33f3238fc4 100644
--- a/src/pico_service.rs
+++ b/src/pico_service.rs
@@ -1,23 +1,26 @@
 use crate::tlog;
 use crate::traft::error::Error;
 use crate::unwrap_ok_or;
+use std::cell::RefCell;
 use std::fs::File;
 use std::io::Read;
 use std::os::unix::fs::PermissionsExt as _;
 use std::path::Path;
+use std::rc::Rc;
 
-/// Password of the special system user "pico_service".
-///
-/// It is stored in a global variable, because we need to access it from
-/// different places in code when creating iproto connections to other instances.
-// TODO: for chap-sha authentication method we only need to store the sha1 hash
-// of the password, but our iproto clients don't yet support this and also sha1
-// is not a secure hash anyway, so ...
-static mut PICO_SERVICE_PASSWORD: Option<String> = None;
+thread_local! {
+    /// Password of the special system user "pico_service".
+    ///
+    /// It is stored in a global variable, because we need to access it from
+    /// different places in code when creating iproto connections to other instances.
+    // TODO: for chap-sha authentication method we only need to store the sha1 hash
+    // of the password, but our iproto clients don't yet support this and also sha1
+    // is not a secure hash anyway, so ...
+    static PICO_SERVICE_PASSWORD: RefCell<Rc<str>> = RefCell::new(Rc::from(""));
+}
 
-#[inline(always)]
-pub(crate) fn pico_service_password() -> &'static str {
-    unsafe { PICO_SERVICE_PASSWORD.as_deref() }.unwrap_or("")
+pub(crate) fn pico_service_password() -> Rc<str> {
+    PICO_SERVICE_PASSWORD.with_borrow(Rc::clone)
 }
 
 pub(crate) fn read_pico_service_password_from_file(
@@ -69,9 +72,7 @@ pub(crate) fn read_pico_service_password_from_file(
         ));
     }
 
-    unsafe {
-        PICO_SERVICE_PASSWORD = Some(password.into());
-    }
+    PICO_SERVICE_PASSWORD.set(Rc::from(password));
 
     Ok(())
 }
diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs
index fa38f23784..7bca618e61 100644
--- a/src/rpc/mod.rs
+++ b/src/rpc/mod.rs
@@ -160,7 +160,7 @@ where
     let mut config = Config::default();
     config.creds = Some((
         PICO_SERVICE_USER_NAME.into(),
-        pico_service_password().into(),
+        pico_service_password().as_ref().into(),
     ));
     let client = Client::connect_with_config(address, port, config).await?;
 
diff --git a/src/schema.rs b/src/schema.rs
index e9eb85148a..6e008a0175 100644
--- a/src/schema.rs
+++ b/src/schema.rs
@@ -1324,7 +1324,7 @@ pub fn system_user_definitions() -> Vec<(UserDef, Vec<PrivilegeDef>)> {
                 AuthData::new(
                     &AuthMethod::ChapSha1,
                     PICO_SERVICE_USER_NAME,
-                    pico_service_password(),
+                    pico_service_password().as_ref(),
                 )
                 .into_string(),
             )),
diff --git a/src/traft/network.rs b/src/traft/network.rs
index d74415ae42..cab7c8802f 100644
--- a/src/traft/network.rs
+++ b/src/traft/network.rs
@@ -197,7 +197,7 @@ impl PoolWorker {
         let mut config = Config::default();
         config.creds = Some((
             PICO_SERVICE_USER_NAME.into(),
-            pico_service_password().into(),
+            pico_service_password().as_ref().into(),
         ));
         config.connect_timeout = Some(call_timeout);
         let client = ReconnClient::with_config(address.clone(), port, config);
-- 
GitLab