Beenden haengt nicht mehr, Update-Agent startet erst nach Bestaetigung
Beim Updatetest auf der Linux-VM (14.09.2026) zeigte sich zweierlei: 1. Nach "Beenden" blieb der Prozess unbegrenzt stehen - Fenster offen, Port zu, Main-Thread in host.StopAsync(...).GetResult(), selbst SIGTERM ohne Wirkung. Betraf jedes Beenden der Oberflaeche, nicht nur den Update-Weg. Der Main-Thread traegt nach StartWithClassicDesktopLifetime noch Avalonias SynchronizationContext, dessen Dispatcher nicht mehr pumpt. Der Stopp laeuft jetzt per Task.Run ohne diesen Kontext, mit Obergrenze 45 s und Log der Dauer. 2. Der update-agent startete schon beim Klick auf "Installieren". Seine 40 s Wartefrist verstrichen waehrend Download und 10-Sekunden-Sperre, er brach ohne Update ab. Er startet jetzt erst nach bestaetigtem Beenden, Frist 120 s. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -120,7 +120,21 @@ namespace PolyTrader.App.Avalonia
|
||||
finally
|
||||
{
|
||||
// Geordnetes Herunterfahren der Module – erst nach dem Ende der Oberfläche.
|
||||
host.StopAsync(TimeSpan.FromSeconds(30)).GetAwaiter().GetResult();
|
||||
//
|
||||
// NICHT direkt auf diesem Thread warten. Nach StartWithClassicDesktopLifetime trägt der
|
||||
// Main-Thread noch den SynchronizationContext von Avalonia, dessen Dispatcher aber nicht
|
||||
// mehr pumpt. Eine Fortsetzung im Stop-Pfad, die dorthin zurückwill, läuft dann nie - der
|
||||
// Prozess blieb nach "Beenden" am 14.09.2026 auf der Linux-VM unbegrenzt stehen: Fenster
|
||||
// offen, Port zu, Main-Thread in GetResult(), selbst SIGTERM ohne Wirkung. Damit griff
|
||||
// auch kein Update, der update-agent wartete vergeblich auf das Prozessende.
|
||||
// Task.Run startet ohne diesen Kontext; die Obergrenze fängt zusätzlich einen Dienst ab,
|
||||
// der sein Token nicht beachtet.
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
var stop = Task.Run(() => host.StopAsync(TimeSpan.FromSeconds(30)));
|
||||
if (stop.Wait(TimeSpan.FromSeconds(45)))
|
||||
bootLog.Info($"Dienste in {sw.Elapsed.TotalSeconds:0.0} s beendet.");
|
||||
else
|
||||
bootLog.Warning("Dienste nach 45 s noch nicht beendet - Anwendung wird trotzdem geschlossen.");
|
||||
host.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,18 @@ namespace PolyTrader.App.Avalonia.Shell
|
||||
/// Zeigt die Sicherheitsabfrage (Beenden-Schaltfläche 10 s gesperrt) und fährt bei Bestätigung
|
||||
/// herunter. Aus jeder Seite aufrufbar – auch aus Modul-Seiten, die die App nicht kennen.
|
||||
/// </summary>
|
||||
public async void RequestShutdown()
|
||||
public void RequestShutdown() => RequestShutdown(onConfirmed: null);
|
||||
|
||||
/// <summary>
|
||||
/// Wie <see cref="RequestShutdown()"/>, mit einem Schritt zwischen Bestätigung und Herunterfahren.
|
||||
/// </summary>
|
||||
/// <param name="onConfirmed">
|
||||
/// Läuft erst, wenn die Sicherheitsabfrage bestätigt ist - liefert er <c>false</c>, wird nicht
|
||||
/// beendet. Für den Update-Weg: Der update-agent darf erst starten, wenn feststeht, dass die
|
||||
/// Anwendung auch endet. Vorher lief seine Wartefrist schon während der 10-Sekunden-Sperre ab,
|
||||
/// und nach „Abbrechen" wartete er ins Leere.
|
||||
/// </param>
|
||||
public async void RequestShutdown(Func<bool>? onConfirmed)
|
||||
{
|
||||
if (ShutdownConfirmed || _shutdownDialogOpen) return;
|
||||
_shutdownDialogOpen = true;
|
||||
@@ -111,6 +122,7 @@ namespace PolyTrader.App.Avalonia.Shell
|
||||
? await dlg.ShowDialog<bool>(_shell)
|
||||
: await dlg.ShowDialog<bool>(new Window());
|
||||
if (!confirmed) return;
|
||||
if (onConfirmed != null && !onConfirmed()) return;
|
||||
|
||||
ShutdownConfirmed = true;
|
||||
if (global::Avalonia.Application.Current?.ApplicationLifetime
|
||||
|
||||
@@ -269,7 +269,12 @@ namespace PolyTrader.App.Avalonia.Views
|
||||
try { licenseKey = SecretProtection.Unprotect(settings?.LicenseKey ?? string.Empty); }
|
||||
catch { /* siehe CheckForUpdateAsync */ }
|
||||
|
||||
UpdateClient.LaunchUpdateAgent(
|
||||
// Derselbe Weg wie ein Klick auf "Beenden" - inklusive Sicherheitsabfrage. Der Agent startet
|
||||
// aber erst NACH deren Bestätigung: Am 14.09.2026 lief er schon beim Klick auf "Installieren"
|
||||
// los, seine 40 s Wartefrist verstrichen während Download und 10-Sekunden-Sperre, und er
|
||||
// brach ohne Update ab. 120 s decken das Herunterfahren ab (Dienste bis 45 s, siehe
|
||||
// Program.Main); läuft die Anwendung danach noch, verändert der Agent nichts.
|
||||
Func<bool> launchAgent = () => UpdateClient.LaunchUpdateAgent(
|
||||
agentPath: agentPath,
|
||||
projectId: dcOptions.ProjectSlug,
|
||||
channel: dcOptions.Channel,
|
||||
@@ -278,11 +283,12 @@ namespace PolyTrader.App.Avalonia.Views
|
||||
currentVersion: BuildInfo.Version,
|
||||
exitCurrentApp: false,
|
||||
waitForCurrentProcess: true,
|
||||
waitTimeoutSeconds: 40,
|
||||
waitTimeoutSeconds: 120,
|
||||
licenseKey: licenseKey);
|
||||
|
||||
// Derselbe Weg wie ein Klick auf "Beenden" - inklusive Sicherheitsabfrage. Der Agent
|
||||
// wartet ohnehin per --wait-for-pid auf unser Prozessende.
|
||||
if (_uiHost is AvaloniaUiHost shell)
|
||||
shell.RequestShutdown(onConfirmed: launchAgent);
|
||||
else if (launchAgent())
|
||||
_uiHost.RequestShutdown();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user