Fix possible w-lock panic

for a detailed explanation of the issue this commit tries to solve have
a look at

    7b5d37a039

which explains the issue in detail.
This commit is contained in:
Matthias Beyer 2016-08-01 20:31:11 +02:00
parent ea17755ad4
commit 84ae516dc3

View file

@ -428,16 +428,18 @@ impl Store {
.map_err_into(SEK::RetrieveCallError) .map_err_into(SEK::RetrieveCallError)
} }
let entry = try!(self.entries let entry = try!({
.write() self.entries
.map_err(|_| SE::new(SEK::LockPoisoned, None)) .write()
.and_then(|mut es| { .map_err(|_| SE::new(SEK::LockPoisoned, None))
let mut se = es.entry(id.clone()).or_insert_with(|| StoreEntry::new(id.clone())); .and_then(|mut es| {
let entry = se.get_entry(); let mut se = es.entry(id.clone()).or_insert_with(|| StoreEntry::new(id.clone()));
se.status = StoreEntryStatus::Borrowed; let entry = se.get_entry();
entry se.status = StoreEntryStatus::Borrowed;
}) entry
.map_err_into(SEK::RetrieveCallError)); })
.map_err_into(SEK::RetrieveCallError)
});
let mut fle = FileLockEntry::new(self, entry); let mut fle = FileLockEntry::new(self, entry);
self.execute_hooks_for_mut_file(self.post_retrieve_aspects.clone(), &mut fle) self.execute_hooks_for_mut_file(self.post_retrieve_aspects.clone(), &mut fle)
@ -598,23 +600,25 @@ impl Store {
.map_err_into(SEK::DeleteCallError) .map_err_into(SEK::DeleteCallError)
} }
let mut entries = match self.entries.write() { {
Err(_) => return Err(SE::new(SEK::LockPoisoned, None)) let mut entries = match self.entries.write() {
.map_err_into(SEK::DeleteCallError), Err(_) => return Err(SE::new(SEK::LockPoisoned, None))
Ok(e) => e, .map_err_into(SEK::DeleteCallError),
}; Ok(e) => e,
};
// if the entry is currently modified by the user, we cannot drop it // if the entry is currently modified by the user, we cannot drop it
if entries.get(&id).map(|e| e.is_borrowed()).unwrap_or(false) { if entries.get(&id).map(|e| e.is_borrowed()).unwrap_or(false) {
return Err(SE::new(SEK::IdLocked, None)) return Err(SE::new(SEK::IdLocked, None))
.map_err_into(SEK::DeleteCallError); .map_err_into(SEK::DeleteCallError);
} }
// remove the entry first, then the file // remove the entry first, then the file
entries.remove(&id); entries.remove(&id);
if let Err(e) = remove_file(&id) { if let Err(e) = remove_file(&id) {
return Err(SEK::FileError.into_error_with_cause(Box::new(e))) return Err(SEK::FileError.into_error_with_cause(Box::new(e)))
.map_err_into(SEK::DeleteCallError); .map_err_into(SEK::DeleteCallError);
}
} }
self.execute_hooks_for_id(self.post_delete_aspects.clone(), &id) self.execute_hooks_for_id(self.post_delete_aspects.clone(), &id)