From 73314ee985b492634cf810bbdda3db8db0c6300a Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 29 Aug 2019 17:13:32 +0200 Subject: [PATCH] Thread safety when quitting the application: Altering vault states (unlocking/locking/...) will now trigger a listener (on the fx application thread) which sets an AtomicBoolean. Previously the value has been read by an AWT thread from a (non-volatile) BooleanBinding --- .../ui/traymenu/TrayMenuController.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java index 7fdafb05c..220c25b21 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java @@ -1,13 +1,10 @@ package org.cryptomator.ui.traymenu; import javafx.beans.Observable; -import javafx.beans.binding.Bindings; -import javafx.beans.binding.BooleanBinding; import javafx.collections.ObservableList; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.vaults.Vault; import org.cryptomator.ui.fxapp.FxApplication; -import org.fxmisc.easybind.EasyBind; import javax.inject.Inject; import javax.inject.Named; @@ -15,13 +12,13 @@ import java.awt.Desktop; import java.awt.Menu; import java.awt.MenuItem; import java.awt.PopupMenu; -import java.awt.desktop.QuitEvent; import java.awt.desktop.QuitResponse; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.EventObject; import java.util.ResourceBundle; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; @TrayMenuScoped @@ -33,7 +30,7 @@ class TrayMenuController { private final Settings settings; private final ObservableList vaults; private final PopupMenu menu; - private final BooleanBinding allLocked; + private final AtomicBoolean allVaultsAreLocked; @Inject TrayMenuController(ResourceBundle resourceBundle, FxApplicationStarter fxApplicationStarter, @Named("shutdownLatch") CountDownLatch shutdownLatch, Settings settings, ObservableList vaults) { @@ -43,7 +40,7 @@ class TrayMenuController { this.settings = settings; this.vaults = vaults; this.menu = new PopupMenu(); - this.allLocked = Bindings.isEmpty(vaults.filtered(Vault::isUnlocked)); // TODO better use Vault::isNotLocked ;) + this.allVaultsAreLocked = new AtomicBoolean(); } public PopupMenu getMenu() { @@ -73,6 +70,7 @@ class TrayMenuController { private void vaultListChanged(@SuppressWarnings("unused") Observable observable) { rebuildMenu(); + allVaultsAreLocked.set(vaults.stream().allMatch(Vault::isLocked)); } private void rebuildMenu() { @@ -100,7 +98,7 @@ class TrayMenuController { private Menu buildSubmenu(Vault vault) { Menu submenu = new Menu(vault.getDisplayableName()); - + // TODO add action listeners if (vault.isLocked()) { MenuItem unlockItem = new MenuItem(resourceBundle.getString("traymenu.vault.unlock")); @@ -113,7 +111,7 @@ class TrayMenuController { MenuItem revealItem = new MenuItem(resourceBundle.getString("traymenu.vault.reveal")); submenu.add(revealItem); } - + return submenu; } @@ -134,7 +132,7 @@ class TrayMenuController { } private void handleQuitRequest(EventObject e, QuitResponse response) { - if (allLocked.get()) { + if (allVaultsAreLocked.get()) { response.performQuit(); // really? } else { fxApplicationStarter.get(true).thenAccept(app -> app.showQuitWindow(response));