-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Fix issue #1898 - Permit::release() must be called when Mutex::lock() is aborted even if it is in the Waiting state #1902
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,10 +2,12 @@ | |
| #![cfg(feature = "full")] | ||
|
|
||
| use tokio::sync::Mutex; | ||
| use tokio::time::{interval, timeout}; | ||
| use tokio_test::task::spawn; | ||
| use tokio_test::{assert_pending, assert_ready}; | ||
|
|
||
| use std::sync::Arc; | ||
| use std::time::Duration; | ||
|
|
||
| #[test] | ||
| fn straight_execution() { | ||
|
|
@@ -79,3 +81,56 @@ fn lock() { | |
| assert!(*result); | ||
| } | ||
| */ | ||
|
|
||
| #[tokio::main] | ||
| #[test] | ||
| /// Ensure a mutex is unlocked if a future holding the lock | ||
| /// is aborted prematurely. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: It would be good to reference the GitHub issue that these tests reproduce. |
||
| async fn aborted_future_1() { | ||
| let m1: Arc<Mutex<usize>> = Arc::new(Mutex::new(0)); | ||
| { | ||
| let m2 = m1.clone(); | ||
| // Try to lock mutex in a future that is aborted prematurely | ||
| timeout(Duration::from_millis(1u64), async move { | ||
| let mut iv = interval(Duration::from_millis(1000)); | ||
| m2.lock().await; | ||
| iv.tick().await; | ||
| iv.tick().await; | ||
|
Comment on lines
+97
to
+98
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The use of the interval here is a little un-obvious, it could be good if there was a comment explaining what it's doing here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought that the comment Is there a better way to let a future delay its execution than creating an interval and waiting twice?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
You could possibly just use task::yield_now().await;if all you want is to yield to the scheduler so that another task will be polled? But, what you're doing now does make sense, I just thought it would be helpful if there was a comment explaining what it was for.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm going to move forward merging & shipping. We can tweak the test in a follow up PR. |
||
| }) | ||
| .await | ||
| .unwrap_err(); | ||
| } | ||
| // This should succeed as there is no lock left for the mutex. | ||
| timeout(Duration::from_millis(1u64), async move { | ||
| m1.lock().await; | ||
| }) | ||
| .await | ||
| .expect("Mutex is locked"); | ||
| } | ||
|
|
||
| #[tokio::main] | ||
| #[test] | ||
| /// This test is similar to `aborted_future_1` but this time the | ||
| /// aborted future is waiting for the lock. | ||
| async fn aborted_future_2() { | ||
| let m1: Arc<Mutex<usize>> = Arc::new(Mutex::new(0)); | ||
| { | ||
| // Lock mutex | ||
| let _lock = m1.lock().await; | ||
| { | ||
| let m2 = m1.clone(); | ||
| // Try to lock mutex in a future that is aborted prematurely | ||
| timeout(Duration::from_millis(1u64), async move { | ||
| m2.lock().await; | ||
| }) | ||
| .await | ||
| .unwrap_err(); | ||
| } | ||
| } | ||
| // This should succeed as there is no lock left for the mutex. | ||
| timeout(Duration::from_millis(1u64), async move { | ||
| m1.lock().await; | ||
| }) | ||
| .await | ||
| .expect("Mutex is locked"); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.