Fix Haenger beim Anlegen eines DHCP-Pools (bugs.md #11)
SSHTransport.connect()/run() hatten keinen Timeout - im Gegensatz zu RestTransport (timeoutInterval=5). Jeder erste Schreibvorgang einer Session loest ueber ensureSessionBackup() eine dedizierte SSH- Verbindung aus; haengt die, blieb isApplying unbegrenzt aktiv (kein Fehler, kein Recovery, nur Force-Quit). Live vom Nutzer bestaetigt (Experte-Tab, dauerhaft haengend) bevor der Fix geschrieben wurde. Neuer genererischer SSHTransport.withTimeout(_:operation:) (Task- Group-Race gegen eine Deadline), angewendet auf connect() (10s) und run() (30s). 3 neue Regressionstests fuer die Race-Logik isoliert. Nebenbefund: xcodegen generate ueberschreibt Info.plist komplett aus project.yml (kein Merge) - ein Regenerieren fuer die neue Testdatei setzte die Version stillschweigend von 1.1.0 auf 1.0 zurueck. Version jetzt explizit in project.yml verankert. Build + alle 106 Unit-Tests gruen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -324,14 +324,14 @@ Nutzer, da UI-Automatisierung hier nicht verfügbar ist.
|
||||
## 2026-09-17 (Nachtrag 4: Nutzer-gemeldet, live in der App)
|
||||
|
||||
### 11. Hänger beim Anlegen eines DHCP-Pools
|
||||
**Status:** offen (Nutzer-Meldung, Ursache noch nicht bestätigt — siehe Code-Audit unten)
|
||||
**Confidence:** mittel (plausibler Root-Cause-Kandidat per Code-Audit gefunden, noch nicht live
|
||||
reproduziert/bestätigt, da UI-Automatisierung nicht verfügbar ist)
|
||||
**Status:** fixed (Build + 106 Unit-Tests grün, 3 neue Regressionstests — Mechanismus isoliert
|
||||
verifiziert, Root Cause vom Nutzer bestätigt, nicht erneut live im UI nachgestellt)
|
||||
**Confidence:** hoch (Nutzer bestätigte exakt das vorhergesagte Bild — Experte-Tab, dauerhaft
|
||||
hängend, kein Fehlertext — bevor der Fix geschrieben wurde)
|
||||
|
||||
Nutzer-Meldung: "Hänger beim Anlegen eines DHCP-Pools" — App bleibt beim Anlegen eines
|
||||
`/ip pool`-Eintrags hängen. Noch keine weiteren Details bekannt (welcher Bereich — Experte-Tab
|
||||
oder Einrichten-Assistent LAN-Schritt; ob sich die App von selbst erholt oder ein Neustart nötig
|
||||
ist; ob vorher eine Fehlermeldung erscheint).
|
||||
`/ip pool`-Eintrags hängen. Rückfrage bestätigte: Experte-Tab, bleibt dauerhaft hängen (kein
|
||||
Selbst-Erholen, Neustart nötig) — exakt das Bild, das der Code-Audit-Kandidat vorhergesagt hatte.
|
||||
|
||||
**Code-Audit-Befund, plausibler Kandidat:** `SSHTransport.connect()` (`SSHTransport.swift`) setzt
|
||||
für den `Citadel.SSHClient.connect(...)`-Aufruf **keinerlei Timeout** — im Gegensatz zu
|
||||
@@ -350,7 +350,21 @@ plausibler Kandidat, kein reproduzierter Fehler. Gleiche Lücke beträfe auch `C
|
||||
applyViaSSH`/`flushConnections` (beide nutzen ebenfalls `SSHTransport.connect()` ohne Timeout) und
|
||||
`UpdateService`/`FactoryResetService`/`NetworkToolsService`, die dieselbe Transport-Klasse nutzen.
|
||||
|
||||
**Fix-Ansatz (noch nicht umgesetzt):** `SSHTransport.connect()` mit einem Timeout umgeben (z.B.
|
||||
`withThrowingTaskGroup`/`Task.sleep`-Race, ähnlich wie RESTs `timeoutInterval`), damit ein
|
||||
hängender Verbindungsaufbau nach einigen Sekunden als Fehler zurückkommt statt die UI unbegrenzt
|
||||
zu blockieren.
|
||||
**Fix:** neuer generischer `SSHTransport.withTimeout(_:operation:)` (`withThrowingTaskGroup`-Race
|
||||
zwischen der echten Operation und einem `Task.sleep`-Deadline-Task, verliert die Operation den
|
||||
Wettlauf wird sie abgebrochen). Angewendet auf `connect()` (10s) und `run(_:)` (30s, großzügiger
|
||||
bemessen, da Exports/Backups auf schwacher Hardware legitim länger brauchen können). Beide
|
||||
Methoden bleiben `async throws`, keine Signaturänderung für Aufrufer.
|
||||
|
||||
**Verifikation:** die Race-Logik selbst ist per 3 neuer Unit-Tests isoliert bewiesen (unabhängig
|
||||
von Citadel/echtem Netzwerk) — ein hängender Vorgang wirft nach der Deadline (getestet mit
|
||||
200ms statt Produktions-Werten, damit der Test schnell bleibt), ein schneller Vorgang liefert sein
|
||||
Ergebnis unverändert, ein eigener Fehler der Operation selbst propagiert unverändert durch. Nicht
|
||||
erneut live im Experte-Tab nachgestellt (bräuchte einen erneuten, absichtlich provozierten
|
||||
Netzwerk-Hänger) — der Nutzer hat die Ursache aber bereits vor dem Fix exakt bestätigt.
|
||||
|
||||
Nebenbefund beim Umsetzen: `xcodegen generate` überschreibt `Info.plist` komplett aus
|
||||
`project.yml`s `info.properties` (kein Merge mit der Datei auf der Platte) — ein Regenerieren für
|
||||
diese neue Testdatei setzte die App-Version dabei stillschweigend von 1.1.0 auf 1.0 zurück.
|
||||
`CFBundleShortVersionString`/`CFBundleVersion` jetzt explizit in `project.yml` verankert, damit
|
||||
das nicht wieder passiert.
|
||||
|
||||
Reference in New Issue
Block a user