Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01d1a322 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

Fix common::time

If already expired, then you might deadlock select!

Test: cargo test
Tag: #stability
Bug: 190012236
Change-Id: I98fe8efd04e1d76540641f7e64928f67c60ab2b5
parent 51c59227
Loading
Loading
Loading
Loading
+28 −2
Original line number Diff line number Diff line
@@ -36,9 +36,11 @@ impl Alarm {
        read_ready.clear_ready();
        drop(read_ready);
        // Will not block, since we have confirmed it is readable
        if self.fd.get_ref().get().unwrap().is_some() {
            self.fd.get_ref().wait().unwrap();
        }
    }
}

impl Default for Alarm {
    fn default() -> Self {
@@ -66,9 +68,11 @@ impl Interval {
        read_ready.clear_ready();
        drop(read_ready);
        // Will not block, since we have confirmed it is readable
        if self.fd.get_ref().get().unwrap().is_some() {
            self.fd.get_ref().wait().unwrap();
        }
    }
}

fn get_clock() -> ClockId {
    if cfg!(target_os = "android") {
@@ -98,6 +102,28 @@ mod tests {
        });
    }

    #[test]
    fn alarm_cancel_after_expired() {
        let runtime = tokio::runtime::Runtime::new().unwrap();
        runtime.block_on(async {
            let mut alarm = Alarm::new();
            alarm.reset(Duration::from_millis(10));
            tokio::time::sleep(Duration::from_millis(30)).await;
            alarm.cancel();

            for _ in 0..10 {
                let ready_in_10_ms = async {
                    tokio::time::sleep(Duration::from_millis(10)).await;
                };

                tokio::select! {
                    _ = alarm.expired() => (),
                    _ = ready_in_10_ms => (),
                }
            }
        });
    }

    #[test]
    fn alarm_clear_ready_after_expired() {
        // After an alarm expired, we need to make sure we clear ready from AsyncFdReadyGuard.