mirror of
https://github.com/cryptomator/cryptomator.git
synced 2024-11-27 05:50:26 +00:00
Some shutdown hook refactorings for #980
This commit is contained in:
parent
362b225d66
commit
ac536ba125
@ -67,7 +67,7 @@ public abstract class CommonsModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static ScheduledExecutorService provideScheduledExecutorService(@Named("shutdownTaskScheduler") Consumer<Runnable> shutdownTaskScheduler) {
|
||||
static ScheduledExecutorService provideScheduledExecutorService(ShutdownHook shutdownHook) {
|
||||
final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(NUM_SCHEDULER_THREADS, r -> {
|
||||
Thread t = new Thread(r);
|
||||
@ -75,7 +75,7 @@ public abstract class CommonsModule {
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
shutdownTaskScheduler.accept(executorService::shutdown);
|
||||
shutdownHook.runOnShutdown(executorService::shutdown);
|
||||
return executorService;
|
||||
}
|
||||
|
||||
|
@ -3,46 +3,48 @@
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the accompanying LICENSE file.
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.launcher;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
package org.cryptomator.common;
|
||||
|
||||
import com.google.common.util.concurrent.Runnables;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
@Singleton
|
||||
class CleanShutdownPerformer extends Thread {
|
||||
public class ShutdownHook extends Thread {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CleanShutdownPerformer.class);
|
||||
private final ConcurrentMap<Runnable, Boolean> tasks = new ConcurrentHashMap<>();
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ShutdownHook.class);
|
||||
private static final Runnable POISON = Runnables.doNothing();
|
||||
|
||||
private final Queue<Runnable> tasks = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Inject
|
||||
CleanShutdownPerformer() {
|
||||
ShutdownHook() {
|
||||
super(null, null, "ShutdownTasks", 0);
|
||||
Runtime.getRuntime().addShutdownHook(this);
|
||||
LOG.debug("Registered shutdown hook.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.debug("Running graceful shutdown tasks...");
|
||||
tasks.keySet().forEach(r -> {
|
||||
tasks.add(POISON);
|
||||
Runnable task;
|
||||
while ((task = tasks.remove()) != POISON) {
|
||||
try {
|
||||
r.run();
|
||||
task.run();
|
||||
} catch (RuntimeException e) {
|
||||
LOG.error("Exception while shutting down.", e);
|
||||
}
|
||||
});
|
||||
tasks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void scheduleShutdownTask(Runnable task) {
|
||||
tasks.put(task, Boolean.TRUE);
|
||||
}
|
||||
|
||||
void registerShutdownHook() {
|
||||
Runtime.getRuntime().addShutdownHook(this);
|
||||
public void runOnShutdown(Runnable task) {
|
||||
tasks.add(task);
|
||||
}
|
||||
|
||||
}
|
@ -32,17 +32,15 @@ public class Cryptomator {
|
||||
private final IpcFactory ipcFactory;
|
||||
private final Optional<String> applicationVersion;
|
||||
private final CountDownLatch shutdownLatch;
|
||||
private final CleanShutdownPerformer shutdownPerformer;
|
||||
private final UiLauncher uiLauncher;
|
||||
|
||||
@Inject
|
||||
Cryptomator(LoggerConfiguration logConfig, DebugMode debugMode, IpcFactory ipcFactory, @Named("applicationVersion") Optional<String> applicationVersion, @Named("shutdownLatch") CountDownLatch shutdownLatch, CleanShutdownPerformer shutdownPerformer, UiLauncher uiLauncher) {
|
||||
Cryptomator(LoggerConfiguration logConfig, DebugMode debugMode, IpcFactory ipcFactory, @Named("applicationVersion") Optional<String> applicationVersion, @Named("shutdownLatch") CountDownLatch shutdownLatch, UiLauncher uiLauncher) {
|
||||
this.logConfig = logConfig;
|
||||
this.debugMode = debugMode;
|
||||
this.ipcFactory = ipcFactory;
|
||||
this.applicationVersion = applicationVersion;
|
||||
this.shutdownLatch = shutdownLatch;
|
||||
this.shutdownPerformer = shutdownPerformer;
|
||||
this.uiLauncher = uiLauncher;
|
||||
}
|
||||
|
||||
@ -90,7 +88,6 @@ public class Cryptomator {
|
||||
*/
|
||||
private int runGuiApplication() {
|
||||
try {
|
||||
shutdownPerformer.registerShutdownHook();
|
||||
uiLauncher.launch();
|
||||
shutdownLatch.await();
|
||||
LOG.info("UI shut down");
|
||||
|
@ -7,18 +7,10 @@ import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Module
|
||||
class CryptomatorModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("shutdownTaskScheduler")
|
||||
Consumer<Runnable> provideShutdownTaskScheduler(CleanShutdownPerformer shutdownPerformer) {
|
||||
return shutdownPerformer::scheduleShutdownTask;
|
||||
}
|
||||
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("shutdownLatch")
|
||||
|
@ -3,9 +3,11 @@ package org.cryptomator.ui.traymenu;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.cryptomator.common.ShutdownHook;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.common.vaults.VaultState;
|
||||
import org.cryptomator.common.vaults.Volume;
|
||||
import org.cryptomator.ui.fxapp.FxApplication;
|
||||
import org.cryptomator.ui.launcher.FxApplicationStarter;
|
||||
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
|
||||
@ -38,17 +40,17 @@ class TrayMenuController {
|
||||
private final ResourceBundle resourceBundle;
|
||||
private final FxApplicationStarter fxApplicationStarter;
|
||||
private final CountDownLatch shutdownLatch;
|
||||
private final Settings settings;
|
||||
private final ShutdownHook shutdownHook;
|
||||
private final ObservableList<Vault> vaults;
|
||||
private final PopupMenu menu;
|
||||
private final AtomicBoolean allowSuddenTermination;
|
||||
|
||||
@Inject
|
||||
TrayMenuController(ResourceBundle resourceBundle, FxApplicationStarter fxApplicationStarter, @Named("shutdownLatch") CountDownLatch shutdownLatch, Settings settings, ObservableList<Vault> vaults) {
|
||||
TrayMenuController(ResourceBundle resourceBundle, FxApplicationStarter fxApplicationStarter, @Named("shutdownLatch") CountDownLatch shutdownLatch, ShutdownHook shutdownHook, ObservableList<Vault> vaults) {
|
||||
this.resourceBundle = resourceBundle;
|
||||
this.fxApplicationStarter = fxApplicationStarter;
|
||||
this.shutdownLatch = shutdownLatch;
|
||||
this.settings = settings;
|
||||
this.shutdownHook = shutdownHook;
|
||||
this.vaults = vaults;
|
||||
this.menu = new PopupMenu();
|
||||
this.allowSuddenTermination = new AtomicBoolean(true);
|
||||
@ -72,6 +74,7 @@ class TrayMenuController {
|
||||
if (Desktop.getDesktop().isSupported(Desktop.Action.APP_QUIT_HANDLER)) {
|
||||
Desktop.getDesktop().setQuitHandler(this::handleQuitRequest);
|
||||
}
|
||||
shutdownHook.runOnShutdown(this::forceUnmountRemainingVaults);
|
||||
|
||||
// allow sudden termination
|
||||
if (Desktop.getDesktop().isSupported(Desktop.Action.APP_SUDDEN_TERMINATION)) {
|
||||
@ -175,4 +178,16 @@ class TrayMenuController {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void forceUnmountRemainingVaults() {
|
||||
for (Vault vault : vaults) {
|
||||
if (vault.isUnlocked()) {
|
||||
try {
|
||||
vault.lock(true);
|
||||
} catch (Volume.VolumeException e) {
|
||||
LOG.error("Failed to unmount vault " + vault.getPath(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user