Recover poisoned shared-state locks
This commit is contained in:
@@ -362,6 +362,15 @@ fn optional_text(value: &str) -> Option<String> {
|
||||
(!value.is_empty()).then(|| value.to_owned())
|
||||
}
|
||||
|
||||
fn update_runtime_preferences(
|
||||
runtime_preferences: &RwLock<AppPreferences>,
|
||||
preferences: &AppPreferences,
|
||||
) {
|
||||
*runtime_preferences
|
||||
.write()
|
||||
.unwrap_or_else(|poisoned| poisoned.into_inner()) = preferences.clone();
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub(super) fn open_preferences(&mut self) {
|
||||
if self.database.is_none() || self.pending_project_path.is_some() || self.choosing_folder {
|
||||
@@ -457,9 +466,7 @@ impl App {
|
||||
Ok(preferences) => {
|
||||
self.preferences = preferences;
|
||||
#[cfg(target_os = "macos")]
|
||||
if let Ok(mut runtime_preferences) = self.runtime_preferences.write() {
|
||||
*runtime_preferences = self.preferences.clone();
|
||||
}
|
||||
update_runtime_preferences(&self.runtime_preferences, &self.preferences);
|
||||
#[cfg(target_os = "macos")]
|
||||
if let Some(endpoint) = pending_endpoint {
|
||||
self._endpoint = Some(endpoint);
|
||||
@@ -474,3 +481,33 @@ impl App {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn runtime_preferences_update_after_lock_poisoning() {
|
||||
let runtime = Arc::new(RwLock::new(AppPreferences::default()));
|
||||
let poisoned = Arc::clone(&runtime);
|
||||
let _ = std::thread::spawn(move || {
|
||||
let _guard = poisoned.write().unwrap();
|
||||
panic!("poison preference lock");
|
||||
})
|
||||
.join();
|
||||
let preferences = AppPreferences {
|
||||
endpoint_port: 4567,
|
||||
..AppPreferences::default()
|
||||
};
|
||||
|
||||
update_runtime_preferences(&runtime, &preferences);
|
||||
|
||||
assert_eq!(
|
||||
runtime
|
||||
.read()
|
||||
.unwrap_or_else(|poisoned| poisoned.into_inner())
|
||||
.endpoint_port,
|
||||
4567
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user