mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-04-27 11:56:05 +02:00
fix(store): dead lock trying to set while exiting (#3395)
* fix(store): dead lock trying to set while exiting * Add change file
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
store: patch
|
||||
store-js: patch
|
||||
---
|
||||
|
||||
Fix a deadlock when calling `Store::set` while exiting (on `RunEvent::Exit`)
|
||||
@@ -15,7 +15,7 @@ pub use serde_json::Value as JsonValue;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
path::{Path, PathBuf},
|
||||
sync::{Arc, Mutex},
|
||||
sync::{Arc, RwLock},
|
||||
time::Duration,
|
||||
};
|
||||
pub use store::{resolve_store_path, DeserializeFn, SerializeFn, Store, StoreBuilder};
|
||||
@@ -39,7 +39,7 @@ struct ChangePayload<'a> {
|
||||
|
||||
#[derive(Debug)]
|
||||
struct StoreState {
|
||||
stores: Arc<Mutex<HashMap<PathBuf, ResourceId>>>,
|
||||
stores: Arc<RwLock<HashMap<PathBuf, ResourceId>>>,
|
||||
serialize_fns: HashMap<String, SerializeFn>,
|
||||
deserialize_fns: HashMap<String, DeserializeFn>,
|
||||
default_serialize: SerializeFn,
|
||||
@@ -139,7 +139,7 @@ async fn get_store<R: Runtime>(
|
||||
store_state: State<'_, StoreState>,
|
||||
path: PathBuf,
|
||||
) -> Result<Option<ResourceId>> {
|
||||
let stores = store_state.stores.lock().unwrap();
|
||||
let stores = store_state.stores.read().unwrap();
|
||||
Ok(stores.get(&resolve_store_path(&app, path)?).copied())
|
||||
}
|
||||
|
||||
@@ -317,7 +317,7 @@ impl<R: Runtime, T: Manager<R>> StoreExt<R> for T {
|
||||
|
||||
fn get_store(&self, path: impl AsRef<Path>) -> Option<Arc<Store<R>>> {
|
||||
let collection = self.state::<StoreState>();
|
||||
let stores = collection.stores.lock().unwrap();
|
||||
let stores = collection.stores.read().unwrap();
|
||||
stores
|
||||
.get(&resolve_store_path(self.app_handle(), path.as_ref()).ok()?)
|
||||
.and_then(|rid| self.resources_table().get(*rid).ok())
|
||||
@@ -437,7 +437,7 @@ impl Builder {
|
||||
])
|
||||
.setup(move |app_handle, _api| {
|
||||
app_handle.manage(StoreState {
|
||||
stores: Arc::new(Mutex::new(HashMap::new())),
|
||||
stores: Arc::new(RwLock::new(HashMap::new())),
|
||||
serialize_fns: self.serialize_fns,
|
||||
deserialize_fns: self.deserialize_fns,
|
||||
default_serialize: self.default_serialize,
|
||||
@@ -448,7 +448,7 @@ impl Builder {
|
||||
.on_event(|app_handle, event| {
|
||||
if let RunEvent::Exit = event {
|
||||
let collection = app_handle.state::<StoreState>();
|
||||
let stores = collection.stores.lock().unwrap();
|
||||
let stores = collection.stores.read().unwrap();
|
||||
for (path, rid) in stores.iter() {
|
||||
if let Ok(store) = app_handle.resources_table().get::<Store<R>>(*rid) {
|
||||
if let Err(err) = store.save() {
|
||||
|
||||
@@ -188,7 +188,7 @@ impl<R: Runtime> StoreBuilder<R> {
|
||||
|
||||
pub(crate) fn build_inner(mut self) -> crate::Result<(Arc<Store<R>>, ResourceId)> {
|
||||
let stores = self.app.state::<StoreState>().stores.clone();
|
||||
let mut stores = stores.lock().unwrap();
|
||||
let mut stores = stores.write().unwrap();
|
||||
|
||||
self.path = resolve_store_path(&self.app, self.path)?;
|
||||
|
||||
@@ -403,7 +403,7 @@ impl<R: Runtime> StoreInner<R> {
|
||||
|
||||
fn emit_change_event(&self, key: &str, value: Option<&JsonValue>) -> crate::Result<()> {
|
||||
let state = self.app.state::<StoreState>();
|
||||
let stores = state.stores.lock().unwrap();
|
||||
let stores = state.stores.read().unwrap();
|
||||
let exists = value.is_some();
|
||||
self.app.emit(
|
||||
"store://change",
|
||||
@@ -438,7 +438,7 @@ impl<R: Runtime> Resource for Store<R> {
|
||||
fn close(self: Arc<Self>) {
|
||||
let store = self.store.lock().unwrap();
|
||||
let state = store.app.state::<StoreState>();
|
||||
let mut stores = state.stores.lock().unwrap();
|
||||
let mut stores = state.stores.write().unwrap();
|
||||
stores.remove(&store.path);
|
||||
}
|
||||
}
|
||||
@@ -554,7 +554,7 @@ impl<R: Runtime> Store<R> {
|
||||
let store = self.store.lock().unwrap();
|
||||
let app = store.app.clone();
|
||||
let state = app.state::<StoreState>();
|
||||
let stores = state.stores.lock().unwrap();
|
||||
let stores = state.stores.read().unwrap();
|
||||
if let Some(rid) = stores.get(&store.path).copied() {
|
||||
drop(store);
|
||||
drop(stores);
|
||||
|
||||
Reference in New Issue
Block a user