Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bitreq/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl Client {

// Try to get cached connection
let conn_opt = {
let state = self.r#async.lock().unwrap();
let state = lock!(self.r#async);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not believe any of the calls within either lock here can panic at all.


if let Some(conn) = state.connections.get(&owned_key) {
Some(Arc::clone(conn))
Expand All @@ -80,7 +80,7 @@ impl Client {
let connection = AsyncConnection::new(key, parsed_request.timeout_at).await?;
let connection = Arc::new(connection);

let mut state = self.r#async.lock().unwrap();
let mut state = lock!(self.r#async);
if let hash_map::Entry::Vacant(entry) = state.connections.entry(owned_key) {
entry.insert(Arc::clone(&connection));
state.lru_order.push_back(key.into());
Expand Down
8 changes: 4 additions & 4 deletions bitreq/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ impl AsyncConnection {
request: ParsedRequest,
) -> Pin<Box<dyn Future<Output = Result<Response, Error>> + Send + 'a>> {
Box::pin(async move {
let conn = Arc::clone(&*self.0.lock().unwrap());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ISTM all of the locks for this mutex are only held on one line and used to clone or assign the Arc, I don't believe that can panic?

let conn = Arc::clone(&*lock!(self.0));
#[cfg(debug_assertions)]
{
let next_read = conn.readable_request_id.load(Ordering::Acquire);
Expand Down Expand Up @@ -427,7 +427,7 @@ impl AsyncConnection {
let new_connection =
AsyncConnection::new(request.connection_params(), request.timeout_at)
.await?;
*self.0.lock().unwrap() = Arc::clone(&*new_connection.0.lock().unwrap());
*lock!(self.0) = Arc::clone(&*lock!(new_connection.0));
core::mem::drop(read);
// Note that this cannot recurse infinitely as we'll always be able to send at
// least one request on the new socket (though some other request may race us
Expand All @@ -444,7 +444,7 @@ impl AsyncConnection {
Self::timeout(request.timeout_at, conn.write.lock()).await?
};

let socket_timeout = *conn.socket_new_requests_timeout.lock().unwrap();
let socket_timeout = *lock!(conn.socket_new_requests_timeout);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, good catch I believe this mutex shouldn't be held nearly as long as it is, it should only be required for the next line then should be dropped.

let socket_timed_out = Instant::now() > socket_timeout;

request_id = conn.next_request_id.fetch_add(1, Ordering::Relaxed);
Expand Down Expand Up @@ -545,7 +545,7 @@ impl AsyncConnection {
match k.trim() {
"timeout" => {
let timeout_secs = (v as u64).saturating_sub(1);
*conn.socket_new_requests_timeout.lock().unwrap() =
*lock!(conn.socket_new_requests_timeout) =
Instant::now()
.checked_add(Duration::from_secs(timeout_secs))
.unwrap_or(Instant::now());
Expand Down
23 changes: 23 additions & 0 deletions bitreq/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,29 @@

extern crate alloc;

/// Acquires a mutex lock, recovering from poisoning.
///
/// A mutex becomes poisoned when a thread panics while holding the lock.
/// This macro ignores poisoning and returns the guard anyway, which is
/// usually the right behavior since:
/// - The data may still be in a valid state
/// - Propagating panics across threads is rarely useful
///
/// # Example
///
/// ```ignore
/// use std::sync::Mutex;
///
/// let mutex = Mutex::new(42);
/// let guard = lock!(mutex);
/// ```
#[cfg(feature = "async")]
macro_rules! lock {
($mutex:expr) => {
$mutex.lock().unwrap_or_else(|e| e.into_inner())
};
}

#[cfg(feature = "std")]
mod client;
#[cfg(feature = "std")]
Expand Down