Browse Source

imap: prevent deadlock in watch::examine_updates

uid_store.mailboxes was locked before calling examine_updates, which
calls examine_mailbox() which also attempts to lock uid_store.mailboxes
async
Manos Pitsidianakis 2 years ago
parent
commit
0a7f283582
Signed by: epilys GPG Key ID: 73627C2F690DF710
  1. 2
      melib/src/backends/imap.rs
  2. 16
      melib/src/backends/imap/watch.rs

2
melib/src/backends/imap.rs

@ -230,7 +230,7 @@ impl MailBackend for ImapType {
.map(std::clone::Clone::clone)
.unwrap();
let mut conn = main_conn.lock().await;
watch::examine_updates(&inbox, &mut conn, &uid_store).await?;
watch::examine_updates(inbox, &mut conn, &uid_store).await?;
Ok(())
}))
}

16
melib/src/backends/imap/watch.rs

@ -60,8 +60,11 @@ pub async fn poll_with_examine(kit: ImapWatchKit) -> Result<()> {
conn.connect().await?;
let mut response = String::with_capacity(8 * 1024);
loop {
let mailboxes = uid_store.mailboxes.lock().await;
for mailbox in mailboxes.values() {
let mailboxes: HashMap<MailboxHash, ImapMailbox> = {
let mailboxes_lck = uid_store.mailboxes.lock().await;
mailboxes_lck.clone()
};
for (_, mailbox) in mailboxes {
examine_updates(mailbox, &mut conn, &uid_store).await?;
}
let mut main_conn = main_conn.lock().await;
@ -188,8 +191,11 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
if now.duration_since(watch) >= _5_MINS {
/* Time to poll all inboxes */
let mut conn = main_conn.lock().await;
let mailboxes = uid_store.mailboxes.lock().await;
for mailbox in mailboxes.values() {
let mailboxes: HashMap<MailboxHash, ImapMailbox> = {
let mailboxes_lck = uid_store.mailboxes.lock().await;
mailboxes_lck.clone()
};
for (_, mailbox) in mailboxes {
exit_on_error!(
conn,
mailbox_hash,
@ -505,7 +511,7 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
}
pub async fn examine_updates(
mailbox: &ImapMailbox,
mailbox: ImapMailbox,
conn: &mut ImapConnection,
uid_store: &Arc<UIDStore>,
) -> Result<()> {

Loading…
Cancel
Save