Skip to content

Commit 5377187

Browse files
committed
Recover from poisoning of internal cache locks
Since they only contain cached values, it's reasonable to overwrite the value with a new empty map and go from there. This doesn't affect the lock used in the FFI layer because that protects caller-provided state, and it doesn't change the function return types to avoid breaking backwards compatibility.
1 parent 7871fcf commit 5377187

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

src/function/eval.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::collections::HashMap;
12
use std::ffi::OsStr;
23
use std::fs::{read_dir, DirEntry, File};
34
use std::hash::Hasher;
@@ -208,10 +209,14 @@ fn evaluate_checksum(state: &State, file_path: &Path, crc: u32) -> Result<bool,
208209
}
209210

210211
let calculated_crc = hasher.finalize();
211-
if let Ok(mut writer) = state.crc_cache.write() {
212-
if let Some(key) = lowercase(file_path) {
213-
writer.insert(key, calculated_crc);
214-
}
212+
let mut writer = state.crc_cache.write().unwrap_or_else(|mut e| {
213+
**e.get_mut() = HashMap::new();
214+
state.crc_cache.clear_poison();
215+
e.into_inner()
216+
});
217+
218+
if let Some(key) = lowercase(file_path) {
219+
writer.insert(key, calculated_crc);
215220
}
216221

217222
Ok(calculated_crc == crc)
@@ -352,9 +357,13 @@ impl Function {
352357

353358
if self.is_slow() {
354359
if let Ok(function_result) = result {
355-
if let Ok(mut writer) = state.condition_cache.write() {
356-
writer.insert(self.clone(), function_result);
357-
}
360+
let mut writer = state.condition_cache.write().unwrap_or_else(|mut e| {
361+
**e.get_mut() = HashMap::new();
362+
state.condition_cache.clear_poison();
363+
e.into_inner()
364+
});
365+
366+
writer.insert(self.clone(), function_result);
358367
}
359368
}
360369

src/lib.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@ impl State {
117117
&mut self,
118118
plugin_crcs: &[(T, u32)],
119119
) -> Result<(), PoisonError<RwLockWriteGuard<HashMap<String, u32>>>> {
120-
let mut writer = self.crc_cache.write()?;
120+
let mut writer = self.crc_cache.write().unwrap_or_else(|mut e| {
121+
**e.get_mut() = HashMap::new();
122+
self.crc_cache.clear_poison();
123+
e.into_inner()
124+
});
121125

122126
writer.deref_mut().clear();
123127
writer.deref_mut().extend(
@@ -132,7 +136,13 @@ impl State {
132136
pub fn clear_condition_cache(
133137
&mut self,
134138
) -> Result<(), PoisonError<RwLockWriteGuard<HashMap<Function, bool>>>> {
135-
self.condition_cache.write().map(|mut c| c.clear())
139+
let mut writer = self.condition_cache.write().unwrap_or_else(|mut e| {
140+
**e.get_mut() = HashMap::new();
141+
self.crc_cache.clear_poison();
142+
e.into_inner()
143+
});
144+
writer.clear();
145+
Ok(())
136146
}
137147

138148
pub fn set_additional_data_paths(&mut self, additional_data_paths: Vec<PathBuf>) {

0 commit comments

Comments
 (0)