aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2019-07-09 10:44:45 +0000
committerRobin Krahl <robin.krahl@ireas.org>2019-07-09 12:47:26 +0200
commit5e8f0fbaf6df0cb919e4b02401cc21d5280bf09c (patch)
tree2495451253d9634e2ef1b5f4972bea93d634c2d7 /src
parent88b32f5c2187e59fece93cd245aeadb4e5f9e04a (diff)
downloadnitrokey-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.rs32
1 files changed, 31 insertions, 1 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 4e45877..a4402c5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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`][]).