Bugfix/backup lock (#1093)

* add write lock before getting model

* update compat cargo.lock file

* update encryptfs passphrase cmd

* add additional safeguards around dropping stdin handles

* proper lock ordering for server status
This commit is contained in:
Lucy C
2022-01-21 10:53:59 -07:00
committed by Aiden McClelland
parent 5d9f7e412c
commit 5b87aca298
5 changed files with 40 additions and 32 deletions

View File

@@ -109,6 +109,9 @@ impl DockerAction {
.write_all(input)
.await
.with_kind(crate::ErrorKind::Docker)?;
stdin.flush().await?;
stdin.shutdown().await?;
drop(stdin);
}
enum Race<T> {
Done(T),

View File

@@ -133,7 +133,14 @@ pub async fn backup_all(
}
let revision = assure_backing_up(&mut db).await?;
tokio::task::spawn(async move {
match perform_backup(&ctx, &mut db, backup_guard).await {
let backup_res = perform_backup(&ctx, &mut db, backup_guard).await;
let status_model = crate::db::DatabaseModel::new().server_info().status();
status_model
.clone()
.lock(&mut db, LockType::Write)
.await
.expect("failed to lock server status");
match backup_res {
Ok(report) if report.iter().all(|(_, rep)| rep.error.is_none()) => ctx
.notification_manager
.notify(
@@ -195,9 +202,7 @@ pub async fn backup_all(
.expect("failed to send notification");
}
}
crate::db::DatabaseModel::new()
.server_info()
.status()
status_model
.put(&mut db, &ServerStatus::Running)
.await
.expect("failed to change server status");
@@ -268,6 +273,7 @@ async fn perform_backup<Db: DbHandle>(
let main_status_model = installed_model.clone().status().main();
let mut tx = db.begin().await?; // for lock scope
main_status_model.lock(&mut tx, LockType::Write).await?;
let (started, health) = match main_status_model.get(&mut tx, true).await?.into_owned() {
MainStatus::Starting => (Some(Utc::now()), Default::default()),
MainStatus::Running { started, health } => (Some(started), health.clone()),

View File

@@ -23,8 +23,8 @@ pub async fn mount_ecryptfs<P0: AsRef<Path>, P1: AsRef<Path>>(
.arg(src.as_ref())
.arg(dst.as_ref())
.arg("-o")
// for more information `man ecryptfs`
.arg(format!("key=passphrase,passwd={},ecryptfs_cipher=aes,ecryptfs_key_bytes=32,ecryptfs_passthrough=n,ecryptfs_enable_filename_crypto=y", key))
// for more information `man ecryptfs`
.arg(format!("key=passphrase:passphrase_passwd={},ecryptfs_cipher=aes,ecryptfs_key_bytes=32,ecryptfs_passthrough=n,ecryptfs_enable_filename_crypto=y", key))
.stdin(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()?;

View File

@@ -426,7 +426,7 @@ impl Manager {
}
Ok(())
}
/// this will depend on locks to main status. if you hold any locks when calling this function that conflict, this will deadlock
pub async fn synchronize(&self) {
self.shared.synchronize_now.notify_waiters();
self.shared.synchronized.notified().await