Rework operation mode error handling

This commit is contained in:
crschnick
2023-11-28 14:54:52 +00:00
parent 1ea317d05c
commit 68c42bfc3d
9 changed files with 68 additions and 51 deletions

View File

@@ -4,6 +4,7 @@ import io.xpipe.app.core.*;
import io.xpipe.app.ext.DataStoreProviders;
import io.xpipe.app.issue.*;
import io.xpipe.app.launcher.LauncherCommand;
import io.xpipe.app.util.PlatformState;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.app.util.XPipeSession;
import io.xpipe.core.store.LocalStore;
@@ -121,10 +122,21 @@ public abstract class OperationMode {
}
public static void switchToAsync(OperationMode newMode) {
ThreadHelper.createPlatformThread("mode switcher", false, () -> switchTo(newMode)).start();
ThreadHelper.createPlatformThread("mode switcher", false, () -> {
switchToSyncIfPossible(newMode);
}).start();
}
public static void switchTo(OperationMode newMode) {
public static void switchToSyncOrThrow(OperationMode newMode) throws Throwable {
TrackEvent.info("Attempting to switch mode to " + newMode.getId());
if (!newMode.isSupported()) {
throw PlatformState.getLastError() != null ? PlatformState.getLastError() : new IllegalStateException("Unsupported operation mode: " + newMode.getId());
}
set(newMode);
}
public static void switchToSyncIfPossible(OperationMode newMode) {
TrackEvent.info("Attempting to switch mode to " + newMode.getId());
if (newMode.equals(TRAY) && !TRAY.isSupported()) {
@@ -142,6 +154,7 @@ public abstract class OperationMode {
set(newMode);
}
public static void switchUp(OperationMode newMode) {
if (newMode == BACKGROUND) {
return;

View File

@@ -13,8 +13,8 @@ public abstract class PlatformMode extends OperationMode {
@Override
public boolean isSupported() {
PlatformState.initPlatform();
return PlatformState.getCurrent() == PlatformState.RUNNING;
var r = PlatformState.initPlatformIfNeeded();
return r;
}
@Override
@@ -24,11 +24,7 @@ public abstract class PlatformMode extends OperationMode {
}
TrackEvent.info("mode", "Platform mode initial setup");
var r = PlatformState.initPlatform();
if (r.isPresent()) {
throw r.get();
}
PlatformState.initPlatformOrThrow();
AppFont.loadFonts();
AppTheme.init();
AppStyle.init();

View File

@@ -26,7 +26,7 @@ public class ModeExchangeImpl extends ModeExchange
.toList()));
}
OperationMode.switchTo(mode);
OperationMode.switchToSyncIfPossible(mode);
return ModeExchange.Response.builder()
.usedMode(OperationMode.map(OperationMode.get()))
.build();

View File

@@ -1,6 +1,5 @@
package io.xpipe.app.issue;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.util.LicenseProvider;
import io.xpipe.app.util.LicenseRequiredException;
@@ -12,23 +11,23 @@ public class GuiErrorHandler extends GuiErrorHandlerBase implements ErrorHandler
public void handle(ErrorEvent event) {
log.handle(event);
if (!OperationMode.GUI.isSupported() || event.isOmitted()) {
if (event.isOmitted()) {
ErrorAction.ignore().handle(event);
return;
}
if (!startupGui(throwable -> {
var second = ErrorEvent.fromThrowable(throwable).build();
log.handle(second);
ErrorAction.ignore().handle(second);
})) {
return;
}
handleGui(event);
}
private void handleGui(ErrorEvent event) {
if (!startupGui(throwable -> {
log.handle(ErrorEvent.fromThrowable(throwable).build());
ErrorAction.ignore().handle(event);
})) {
return;
}
if (event.getThrowable() instanceof LicenseRequiredException lex) {
LicenseProvider.get().showLicenseAlert(lex);
event.setShouldSendDiagnostics(true);

View File

@@ -8,21 +8,16 @@ import java.util.function.Consumer;
public class GuiErrorHandlerBase {
protected boolean startupGui(Consumer<Throwable> onFail) {
var ex = PlatformState.initPlatform();
if (ex.isPresent()) {
onFail.accept(ex.get());
return false;
}
try {
PlatformState.initPlatformOrThrow();
AppProperties.init();
AppState.init();
AppExtensionManager.init(false);
AppI18n.init();
AppStyle.init();
AppTheme.init();
} catch (Throwable r) {
onFail.accept(r);
} catch (Throwable ex) {
onFail.accept(ex);
return false;
}

View File

@@ -16,23 +16,23 @@ public class TerminalErrorHandler extends GuiErrorHandlerBase implements ErrorHa
public void handle(ErrorEvent event) {
log.handle(event);
if (!OperationMode.GUI.isSupported() || event.isOmitted() || OperationMode.isInShutdown()) {
SentryErrorHandler.getInstance().handle(event);
if (event.isOmitted() || OperationMode.isInShutdown()) {
ErrorAction.ignore().handle(event);
OperationMode.halt(1);
return;
}
if (!startupGui(throwable -> {
handleWithSecondaryException(event, throwable);
ErrorAction.ignore().handle(event);
})) {
return;
}
handleGui(event);
}
private void handleGui(ErrorEvent event) {
if (!startupGui(throwable -> {
handleSecondaryException(event, throwable);
ErrorAction.ignore().handle(event);
})) {
return;
}
try {
AppProperties.init();
AppState.init();
@@ -43,7 +43,7 @@ public class TerminalErrorHandler extends GuiErrorHandlerBase implements ErrorHa
ErrorHandlerComp.showAndTryWait(event, true);
} catch (Throwable r) {
event.clearAttachments();
handleSecondaryException(event, r);
handleWithSecondaryException(event, r);
return;
}
@@ -54,13 +54,12 @@ public class TerminalErrorHandler extends GuiErrorHandlerBase implements ErrorHa
OperationMode.halt(1);
}
private void handleSecondaryException(ErrorEvent event, Throwable t) {
log.handle(event);
SentryErrorHandler.getInstance().handle(event);
private void handleWithSecondaryException(ErrorEvent event, Throwable t) {
ErrorAction.ignore().handle(event);
var second = ErrorEvent.fromThrowable(t).build();
log.handle(second);
SentryErrorHandler.getInstance().handle(ErrorEvent.fromThrowable(t).build());
ErrorAction.ignore().handle(second);
OperationMode.halt(1);
}
@@ -89,7 +88,7 @@ public class TerminalErrorHandler extends GuiErrorHandlerBase implements ErrorHa
} catch (Throwable t) {
var event = ErrorEvent.fromThrowable(t).build();
log.handle(event);
SentryErrorHandler.getInstance().handle(event);
ErrorAction.ignore().handle(event);
OperationMode.halt(1);
}
}

View File

@@ -13,6 +13,7 @@ import io.xpipe.beacon.exchange.FocusExchange;
import io.xpipe.beacon.exchange.OpenExchange;
import io.xpipe.core.process.OsType;
import io.xpipe.core.util.XPipeDaemonMode;
import lombok.SneakyThrows;
import picocli.CommandLine;
import java.awt.*;
@@ -118,11 +119,12 @@ public class LauncherCommand implements Callable<Integer> {
}
@Override
@SneakyThrows
public Integer call() {
checkStart();
// Initialize base mode first to have access to the preferences to determine effective mode
OperationMode.switchTo(OperationMode.BACKGROUND);
OperationMode.switchTo(OperationMode.map(getEffectiveMode()));
OperationMode.switchToSyncOrThrow(OperationMode.BACKGROUND);
OperationMode.switchToSyncOrThrow(OperationMode.map(getEffectiveMode()));
LauncherInput.handle(inputs);
// URL open operations have to be handled in a special way on macOS!

View File

@@ -39,7 +39,7 @@ public abstract class LauncherInput {
var requiresPlatform = all.stream().anyMatch(launcherInput -> launcherInput.requiresJavaFXPlatform());
if (requiresPlatform) {
OperationMode.switchTo(OperationMode.GUI);
OperationMode.switchToSyncIfPossible(OperationMode.GUI);
}
var hasGui = OperationMode.get() == OperationMode.GUI;

View File

@@ -21,6 +21,9 @@ public enum PlatformState {
@Setter
private static PlatformState current = PlatformState.NOT_INITIALIZED;
@Getter
private static Exception lastError;
public static void teardown() {
PlatformThread.runLaterIfNeededBlocking(() -> {
// Fix to preserve clipboard contents after shutdown
@@ -36,14 +39,24 @@ public enum PlatformState {
setCurrent(PlatformState.EXITED);
}
public static void initPlatformOrThrow() throws Throwable {
var r = PlatformState.initPlatform();
if (r.isPresent()) {
throw r.get();
public static void initPlatformOrThrow() throws Exception {
initPlatformIfNeeded();
if (lastError != null) {
throw lastError;
}
}
public static Optional<Throwable> initPlatform() {
public static boolean initPlatformIfNeeded() {
if (current == NOT_INITIALIZED) {
var t = PlatformState.initPlatform().orElse(null);
lastError = t instanceof Exception e ? e : t != null ? new Exception(t) : null;
}
return current == RUNNING;
}
private static Optional<Throwable> initPlatform() {
if (current == EXITED) {
return Optional.of(new IllegalStateException("Platform has already exited"));
}