diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/LockNotCompletedException.java b/main/commons/src/main/java/org/cryptomator/common/vaults/LockNotCompletedException.java new file mode 100644 index 000000000..237630da0 --- /dev/null +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/LockNotCompletedException.java @@ -0,0 +1,12 @@ +package org.cryptomator.common.vaults; + +public class LockNotCompletedException extends Exception { + + public LockNotCompletedException(String reason) { + super(reason); + } + + public LockNotCompletedException(Throwable cause) { + super(cause); + } +} diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java b/main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java index f10eb3968..fae92b3b7 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java @@ -140,14 +140,7 @@ public class Vault { cryptoFileSystem.set(fs); try { volume = volumeProvider.get(); - volume.mount(fs, getEffectiveMountFlags(), throwable -> { - LOG.info("Unmounted vault '{}'", getDisplayName()); - destroyCryptoFileSystem(); - state.set(VaultState.Value.LOCKED); - if (throwable != null) { - LOG.warn("Unexpected unmount and lock of vault " + getDisplayName(), throwable); - } - }); + volume.mount(fs, getEffectiveMountFlags(), this::lockOnVolumeExit); } catch (Exception e) { destroyCryptoFileSystem(); throw e; @@ -157,21 +150,32 @@ public class Vault { } } - public synchronized void lock(boolean forced) throws VolumeException { + private void lockOnVolumeExit(Throwable t) { + LOG.info("Unmounted vault '{}'", getDisplayName()); + destroyCryptoFileSystem(); + state.set(VaultState.Value.LOCKED); + if (t != null) { + LOG.warn("Unexpected unmount and lock of vault " + getDisplayName(), t); + } + } + + public synchronized void lock(boolean forced) throws VolumeException, LockNotCompletedException { + //initiate unmount if (forced && volume.supportsForcedUnmount()) { volume.unmountForced(); } else { volume.unmount(); } - destroyCryptoFileSystem(); + + //wait for lockOnVolumeExit to be executed try { boolean locked = state.awaitState(VaultState.Value.LOCKED, 3000, TimeUnit.MILLISECONDS); if (!locked) { - throw new VolumeException("Locking failed"); //FIXME: other exception + throw new LockNotCompletedException("Locking of vault " + this.getDisplayName() + " still in progress."); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw new VolumeException("Lock failed."); //FIXME: other/new exception + throw new LockNotCompletedException(e); } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/common/VaultService.java b/main/ui/src/main/java/org/cryptomator/ui/common/VaultService.java index 6555904e5..b81ddec49 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/common/VaultService.java +++ b/main/ui/src/main/java/org/cryptomator/ui/common/VaultService.java @@ -1,5 +1,6 @@ package org.cryptomator.ui.common; +import org.cryptomator.common.vaults.LockNotCompletedException; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultState; import org.cryptomator.common.vaults.Volume; @@ -175,7 +176,7 @@ public class VaultService { } @Override - protected Vault call() throws Volume.VolumeException { + protected Vault call() throws Volume.VolumeException, LockNotCompletedException { vault.lock(forced); return vault; } diff --git a/main/ui/src/main/java/org/cryptomator/ui/launcher/AppLifecycleListener.java b/main/ui/src/main/java/org/cryptomator/ui/launcher/AppLifecycleListener.java index 5e2ed383a..75af409f1 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/launcher/AppLifecycleListener.java +++ b/main/ui/src/main/java/org/cryptomator/ui/launcher/AppLifecycleListener.java @@ -1,6 +1,7 @@ package org.cryptomator.ui.launcher; import org.cryptomator.common.ShutdownHook; +import org.cryptomator.common.vaults.LockNotCompletedException; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultState; import org.cryptomator.common.vaults.Volume; @@ -129,6 +130,8 @@ public class AppLifecycleListener { vault.lock(true); } catch (Volume.VolumeException e) { LOG.error("Failed to unmount vault " + vault.getPath(), e); + } catch (LockNotCompletedException e) { + LOG.error("Failed to lock vault " + vault.getPath(), e); } } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/lock/LockWorkflow.java b/main/ui/src/main/java/org/cryptomator/ui/lock/LockWorkflow.java index 5566caeb0..87fd486f2 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/lock/LockWorkflow.java +++ b/main/ui/src/main/java/org/cryptomator/ui/lock/LockWorkflow.java @@ -1,6 +1,7 @@ package org.cryptomator.ui.lock; import dagger.Lazy; +import org.cryptomator.common.vaults.LockNotCompletedException; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultState; import org.cryptomator.common.vaults.Volume; @@ -49,10 +50,10 @@ public class LockWorkflow extends Task { } @Override - protected Void call() throws Volume.VolumeException, InterruptedException { + protected Void call() throws Volume.VolumeException, InterruptedException, LockNotCompletedException { try { vault.lock(false); - } catch (Volume.VolumeException e) { + } catch (Volume.VolumeException | LockNotCompletedException e) { LOG.debug("Regular lock of {} failed.", vault.getDisplayName(), e); var decision = askUserForAction(); switch (decision) {