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`][]). | 
