-
Notifications
You must be signed in to change notification settings - Fork 251
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
feat: implement time lease based locks for the CryptoStore
#2140
Conversation
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #2140 +/- ##
==========================================
+ Coverage 76.35% 76.57% +0.22%
==========================================
Files 163 164 +1
Lines 17516 17565 +49
==========================================
+ Hits 13374 13451 +77
+ Misses 4142 4114 -28
☔ View full report in Codecov by Sentry. |
9d6b67f
to
5acbac6
Compare
why do we need time leased locks? when i tested this with file based posix locks, you could acquire the lock no matter how dirtily the process holding the lock got knifed. |
There isn't a great and obvious choice for a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just to note that I've started review. I haven't gotten very far yet, but will continue tomorrow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall it looks good to me :-).
@@ -68,6 +106,16 @@ pub struct CryptoStoreLock { | |||
} | |||
|
|||
impl CryptoStoreLock { | |||
/// Amount of time a lease of the lock should last, in milliseconds. | |||
pub const LEASE_DURATION_MS: u32 = 2000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be 1000, or even 800, so that it cannot be really perceived by the app end-user?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fwiw: we chatted about it, and we'll try renew-every 50ms / lease-for 500ms: still a 1:10 ratio, and the lease should be closer to non-perceivable by the user (ideally we'd go under 300ms, but that seems more dangerous with respect to the scheduler being super busy).
// Clone data to be owned by the task. | ||
let this = self.clone(); | ||
|
||
matrix_sdk_common::executor::spawn(async move { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we sure we don't want to keep a handle to this spawned task, so that we can abort it in case of emergency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's also useful to make sure we don't spawn it multiple times 👍 Added some code to handle that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks good. It would be nice if people on the EX side would test this but I guess that's what the nightly is there for.
From my point of view, we can tweak the timeouts if they end up being too long later on.
match lock.try_lock_once().await? { | ||
Some(guard) => Ok(Some(guard)), | ||
None => { | ||
// We didn't get the lock on the first attempt, so that means that another |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we certain that we don't need to reload when we did acquire the lock on the first attempt? Isn't there a race where we might get the lock just as it was released by the other process?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed you're right! This is going to be more generally fixed by #2155 :-)
Signed-off-by: Benjamin Bouvier <public@benj.me>
See top comment in matrix-sdk-crypto/src/store/locks.rs
Signed-off-by: Benjamin Bouvier <public@benj.me>
… there Signed-off-by: Benjamin Bouvier <public@benj.me>
… failed Signed-off-by: Benjamin Bouvier <public@benj.me>
Signed-off-by: Benjamin Bouvier <public@benj.me>
Signed-off-by: Benjamin Bouvier <public@benj.me>
Signed-off-by: Benjamin Bouvier <public@benj.me>
Signed-off-by: Benjamin Bouvier <public@benj.me>
wat (also don't use `is_terminated` since it doesn't exist on wasm)
// operation | ||
// running in a transaction. | ||
|
||
drop(renew_task.take()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Be careful, it doesn't abort the task!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, TIL. I've added an abort()
that's guarded by #[cfg(not(target_arch = "wasm32"))]
; this code wouldn't work on wasm32 anyways because it's using tokio::sleep.
Tested and this thing is bulletproof, tested on scenarios where both the NSE and Main App did not stop the sync and did not release the lock, and everything worked as expected. |
This implements a new time lease based lock for the
CryptoStore
, that doesn't require explicit unlocking, so that's more robust in the context of #1928, where any process may die because the device is running out of battery, or unexpected flows cause a lock to not be released properly in one or the other process.Notes
insert_custom_value_if_missing
/remove_custom_value
at the moment, but we could remove them if this lock proves to be more robust.