diff options
author | Robin Krahl <robin.krahl@ireas.org> | 2019-07-09 10:44:45 +0000 |
---|---|---|
committer | Robin Krahl <robin.krahl@ireas.org> | 2019-07-09 12:47:26 +0200 |
commit | 5e8f0fbaf6df0cb919e4b02401cc21d5280bf09c (patch) | |
tree | 2495451253d9634e2ef1b5f4972bea93d634c2d7 /src | |
parent | 88b32f5c2187e59fece93cd245aeadb4e5f9e04a (diff) | |
download | nitrokey-rs-5e8f0fbaf6df0cb919e4b02401cc21d5280bf09c.tar.gz nitrokey-rs-5e8f0fbaf6df0cb919e4b02401cc21d5280bf09c.tar.bz2 |
Add force_take function to ignore poisoned cache
The take and take_blocking functions return a PoisonError if the cache
is poisoned, i. e. if a thread panicked while holding the manager. This
is a sensible default behaviour, but for example during testing, one
might want to ignore the poisoned cache. This patch adds the force_take
function that unwraps the PoisonError and returns the cached Manager
even if the cache was poisoned.
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 32 |
1 files changed, 31 insertions, 1 deletions
@@ -377,7 +377,8 @@ pub fn take_blocking() -> Result<sync::MutexGuard<'static, Manager>, Error> { /// /// There may only be one [`Manager`][] instance at the same time. If there already is an /// instance, a [`ConcurrentAccessError`][] is returned. If you want a blocking version, use -/// [`take_blocking`][]. +/// [`take_blocking`][]. If you want to access the manager instance even if the cache is poisoned, +/// use [`force_take`][]. /// /// # Errors /// @@ -385,6 +386,7 @@ pub fn take_blocking() -> Result<sync::MutexGuard<'static, Manager>, Error> { /// - [`PoisonError`][] if the lock is poisoned /// /// [`take_blocking`]: fn.take_blocking.html +/// [`force_take`]: fn.force_take.html /// [`ConcurrentAccessError`]: struct.Error.html#variant.ConcurrentAccessError /// [`PoisonError`]: struct.Error.html#variant.PoisonError /// [`Manager`]: struct.Manager.html @@ -392,6 +394,34 @@ pub fn take() -> Result<sync::MutexGuard<'static, Manager>, Error> { MANAGER.try_lock().map_err(Into::into) } +/// Try to take an instance of the connection manager, ignoring a poisoned cache. +/// +/// There may only be one [`Manager`][] instance at the same time. If there already is an +/// instance, a [`ConcurrentAccessError`][] is returned. If you want a blocking version, use +/// [`take_blocking`][]. +/// +/// If a thread has previously panicked while accessing the manager instance, the cache is +/// poisoned. The default implementation, [`take`][], returns a [`PoisonError`][] on subsequent +/// calls. This implementation ignores the poisoned cache and returns the manager instance. +/// +/// # Errors +/// +/// - [`ConcurrentAccessError`][] if the token for the `Manager` instance cannot be locked +/// +/// [`take`]: fn.take.html +/// [`take_blocking`]: fn.take_blocking.html +/// [`ConcurrentAccessError`]: struct.Error.html#variant.ConcurrentAccessError +/// [`Manager`]: struct.Manager.html +pub fn force_take() -> Result<sync::MutexGuard<'static, Manager>, Error> { + match take() { + Ok(guard) => Ok(guard), + Err(err) => match err { + Error::PoisonError(err) => Ok(err.into_inner()), + err => Err(err), + }, + } +} + /// Enables or disables debug output. Calling this method with `true` is equivalent to setting the /// log level to `Debug`; calling it with `false` is equivalent to the log level `Error` (see /// [`set_log_level`][]). |