chiark / gitweb /
config etc.: avoid accessing the save path without locking it
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 11 Dec 2020 23:25:20 +0000 (23:25 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 11 Dec 2020 23:25:20 +0000 (23:25 +0000)
We panic instead!

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/accounts.rs
src/bin/daemon-otter.rs
src/config.rs
src/global.rs

index 4eaea255cb2c7a10172c868e7545d73d27812d07..38fa32aa7f640cea79d8b4d9248f051e37723808 100644 (file)
@@ -401,7 +401,7 @@ impl AccountsGuard {
 //---------- load/save ----------
 
 fn save_path() -> String {
-  format!("{}/{}", config().save_dir, &ACCOUNTS_FILE)
+  format!("{}/{}", config().save_dir(), &ACCOUNTS_FILE)
 }
 
 #[throws(StartupError)]
index b397c8162378c5e4d6f9fc315a2a6f4e506bf4a1..7241aea3e25dd7155504aafdae3fafedc0b20b1c 100644 (file)
@@ -198,6 +198,7 @@ fn main() {
   nwtemplates::init()?;
   shapelib::load()?;
 
+  c.lock_save_area()?;
   load_accounts()?;
   load_games(&mut AccountsGuard::lock(), &mut games_lock())?;
 
index 6cd592591223d171be67d7897584a3c934604b42..bb8bf4c947000d643ce9cc077008e94e8e2f4e20 100644 (file)
@@ -36,7 +36,7 @@ pub struct ServerConfigSpec {
 
 #[derive(Debug,Clone)]
 pub struct ServerConfig {
-  pub save_dir: String,
+  save_dir: String,
   pub command_socket: String,
   pub debug: bool,
   pub http_port: Option<u16>,
@@ -151,6 +151,26 @@ impl ServerConfig {
     let config = config.try_into()?;
     set_config(config);
   }
+
+  #[throws(AE)]
+  pub fn lock_save_area(&self) {
+    let mut st = GLOBAL.save_area_lock.lock().unwrap();
+    let st = &mut *st;
+    if st.is_none() {
+      let lockfile = format!("{}/lock", config().save_dir);
+      *st = Some((||{
+        let file = File::create(&lockfile).context("open")?;
+        file.try_lock_exclusive().context("lock")?;
+        Ok::<_,AE>(file)
+      })().context(lockfile).context("lock global save area")?);
+    }
+  }
+
+  pub fn save_dir(&self) -> &String {
+    let st = GLOBAL.save_area_lock.lock().unwrap();
+    let mut _f : &File = st.as_ref().unwrap();
+    &self.save_dir
+  }
 }
 
 impl Default for ServerConfig {
index 184c25e10006e430f18b6d51aef3dbb57fbc4ed0..b957ac4f7de410ed9d78959686c089a5c136da71 100644 (file)
@@ -187,7 +187,7 @@ pub struct Global {
   // (perf impact); outermost first, innermost last)
 
   // slow global locks:
-  save_area_lock: Mutex<Option<File>>,
+  pub save_area_lock: Mutex<Option<File>>,
   // <- accounts::accounts ->
   games_table: RwLock<GamesTable>,
 
@@ -831,7 +831,7 @@ enum SavefilenameParseResult {
 }
 
 fn savefilename(name: &InstanceName, prefix: &str, suffix: &str) -> String {
-  [ config().save_dir.as_str(), &"/", prefix ]
+  [ config().save_dir().as_str(), &"/", prefix ]
     .iter().map(Deref::deref)
     .chain(iter::once( name.to_string().as_str() ))
     .chain([ suffix ].iter().map(Deref::deref))
@@ -939,19 +939,6 @@ impl InstanceGuard<'_> {
   fn load_game(accounts: &AccountsGuard,
                games: &mut GamesGuard,
                name: InstanceName) -> Option<InstanceRef> {
-    {
-      let mut st = GLOBAL.save_area_lock.lock().unwrap();
-      let st = &mut *st;
-      if st.is_none() {
-        let lockfile = format!("{}/lock", config().save_dir);
-        *st = Some((||{
-          let file = File::create(&lockfile).context("open")?;
-          file.try_lock_exclusive().context("lock")?;
-          Ok::<_,AE>(file)
-        })().context(lockfile).context("lock global save area")?);
-      }
-    }
-
     let InstanceSaveAccesses::<String,ActualPiecesLoaded>
     { tokens_players, mut ipieces, mut aplayers, acl }
     = match Self::load_something(&name, "a-") {
@@ -1060,7 +1047,7 @@ pub fn load_games(accounts: &mut AccountsGuard,
   use AFState::*;
   use SavefilenameParseResult::*;
   let mut a_leaves = HashMap::new();
-  for de in fs::read_dir(&config().save_dir)? {
+  for de in fs::read_dir(&config().save_dir())? {
     let de = de?;
     let leaf = de.file_name();
     (||{