12 KiB
Verifikation: ereigniszustellung-und-hostgrenzen
Stand nach Behebung: 05.09.2026, aktueller Arbeitsbaum auf 57d6386.
Alle fünf Verifikationsbefunde sind behoben. Die ursprünglichen sechs
Review-Proben bestehen unverändert in ihren Erwartungen; zusätzlich wurden
sie in die Workspace-Regressionen übernommen und um verwandte Pfade ergänzt.
| Dimension | Ergebnis |
|---|---|
| Vollständigkeit | 12/12 Tasks erledigt; ursprüngliche Zuordnung der 9 Delta-Requirements und 33 Szenarien um Korrektur-Nachweise ergänzt. |
| Korrektheit | 419 Workspace-Tests und alle sechs separaten Review-Proben bestanden; keine offenen V1–V5-Befunde. |
| Kohärenz | Gemeinsame Zustellung auch während Eingabe und nach Menüschluss; synchrone LOAD-Wirkungen getrennt, klassische Quellpriorität erhalten. |
Korrekturen und Regressionen
| Befund | Behebung | Nachweis in crates/tb-vm/tests/events.rs |
|---|---|---|
| V1 | Fortsetzbarer Konsolenleser für INPUT, LINE INPUT, INPUT$ und RANDOMIZE ohne Argument. Frame hält Teiltext/Restlänge, Stack hält Operanden und Referenzen. Trap-Unwinding erhält gemeinsam genutzte Locals; Fehler und RETURN label verwerfen abgebrochene Eingaben. | Ursprüngliche Signalprobe; Teiltext/BYREF/Ausdruck, verschachtelte Eingaben mit STOP/CONT, Timer, Redo, lokaler Fehlerhandler, RANDOMIZE und RETURN label. |
| V2 | Implizite Objektaufrufe stellen ausschließlich notwendige LOAD-Handler zu. Deren Rückkehr zieht keine unabhängigen Forms-Ereignisse vor. | LlGg mit Control-Argument, Property-Lesen/-Schreiben, Refresh und LOAD; bestehende Load-vor-Show- und Unload-Tests. |
| V3 | Nach dem Schließen des Menüs wird die gemeinsame Auswahl vor jedem erneuten Warten wiederholt. | Esc bei Zeit 0, UEVENT zugestellt nach genau einem Warteaufruf; bestehende Menüsperrtests einschließlich Forms-Timer. |
| V4 | Modale und modellose Schleifen beenden bei EOF erst, wenn kein Handler mehr zugestellt wurde. | Ursprüngliche MouseDown/Unload-Probe; jeweils zwei Mausereignisse vor EOF ergeben MM in beiden Schleifen. |
| V5 | Getrappte Tasten am Queue-Anfang werden vor der klassischen Quellenauswahl gemeldet. | Gleichzeitiges KEY/UEVENT ergibt KU; Maus vor getrappter Taste bleibt MK. |
Ursprüngliche Befunde — historischer Stand vor der Behebung
Die folgenden Ist-Beobachtungen und Ursachen dokumentieren den fehlgeschlagenen Review vor diesen Korrekturen. Alle fünf sind durch die Nachweise oben geschlossen.
V1 — Während blockierender Eingabe werden eintreffende Traps nicht zugestellt (hoch)
Reproduktion: ON SIGNAL(2) GOSUB H, SIGNAL(2) ON, danach INPUT.
Der Host liefert erst im blockierenden next_event(true) Signal(2), beim
nächsten Aufruf Eingabeende. Der Handler H würde PRINT "H" und END ausführen.
Ist: INPUT, LINE INPUT und INPUT$(1) enden jeweils mit Fehler 62, H läuft nicht. Ohne nachfolgende Eingabe kann die Laufzeit stattdessen erneut blockieren, obwohl der Signal-Trap schon ansteht.
Soll: Vor dem erneuten Blockieren muss der erlaubte Zustellpunkt genutzt werden; H beendet das Programm, Ausgabe H, kein Fehler 62.
Ursache: Der einmalige VM-Check vor der Eingabeinstruktion genügt nicht. RtState::naechste_taste pumpt innerhalb seiner Schleife weitere Ereignisse und blockiert erneut, ohne zur VM-Zustellung zurückzukehren. Dasselbe betrifft die drei genannten Eingabefunktionen über ihren gemeinsamen Leser.
Vertrag: ereignissteuerung / Abschließende Liste der Zustellpunkte,
Signal-Trap auf Betriebssystemsignalen; Design D2; Task 2.1.
Korrektur: Blockierende Eingabe so fortsetzbar machen, dass nach einem
Nicht-Tasten-Ereignis und vor dem nächsten Host-Warten die gemeinsame
VM-Zustellung laufen kann. Eingabepuffer, Referenzen und Operanden erhalten.
V2 — Control-Argumente stellen wartende Forms-Handler mitten in einer Anweisung zu (hoch)
Reproduktion: Fokuswechsel Text1 → Text2. Text1_LostFocus ruft als erste
wirksame Anweisung CALL Mark(Text1) auf; Mark hängt L an eine gemeinsame
Variable, LostFocus danach l. Text2_GotFocus hängt G und g an.
Ist: GgLl. Soll: LlGg.
Ursache: Instr::PushObject
ruft nach dem Ablegen eines bereits geladenen Control-Objekts bedingungslos
dispatch_next_form_event auf. Dadurch läuft GotFocus noch vor dem eigentlichen
CALL, obwohl weder DOEVENTS noch modales Warten vorliegt. Der Schutz am ersten
Stmt-Eintritt und forms_frei werden damit umgangen.
Vertrag: Fokus, Tabreihenfolge und Access-Keys / Handlerwirkungen in
Fokusreihenfolge; Abschließende Liste der Zustellpunkte; Design D1/D2;
Tasks 1.2 und 2.1.
Korrektur: Unabhängig wartende Ereignisse aus Objekt-Opcodes heraus nicht
zustellen. Notwendige synchrone Load-/Unload-Wirkungen gezielt behandeln;
alle Aufrufer von dispatch_next_form_event gegen dieselben Zustellregeln prüfen.
V3 — Menüschließen während SLEEP führt zu erneutem Warten trotz bereitem Trap (hoch)
Reproduktion: Menü offen, UEVENT anstehend, SLEEP 60. Der erste
Host-Warteaufruf liefert Esc bei unveränderter virtueller Zeit 0.
Ist: Esc schließt das Menü; die VM wartet ein zweites Mal bis Hostzeit 60.000 ms. Erst dann läuft der UEVENT-Handler. Soll: Nach Esc läuft der freigegebene Handler ohne zweiten Warteaufruf und beendet SLEEP sofort. Bei einer Wartephase ohne eigene Deadline droht entsprechend Warten auf ein weiteres externes Ereignis.
Ursache: Die klassische Trap-Auswahl in
Vm::zustellen erfolgt vor der
Eingabeverarbeitung. Nachdem Esc die Menüsperre aufgehoben hat, kehrt die
Methode ohne erneute Auswahl zurück;
SLEEP ruft unmittelbar wieder
warten auf.
Vertrag: Menüsystem / Traps ruhen im geöffneten Menü und werden danach fortgesetzt; Abschließende Liste der Zustellpunkte / SLEEP endet durch Ereignis; Design D2/D3; Tasks 2.1/2.2. Korrektur: Nach einer Eingabe, die die Zustellbarkeit verändert, bereite Ereignisse vor jedem weiteren blockierenden Warten erneut auswählen.
V4 — Modale Schleife verliert bereits angenommenes Ereignis unmittelbar vor EOF (hoch)
Reproduktion: Form1.Show 1; nach der zweiten Anzeige liefert der Host
MouseDown und unmittelbar danach Eingabeende. Der MouseDown-Handler hängt M
an und entlädt das Formular.
Ist: VM meldet Ended, die gemeinsame Variable bleibt leer; der Handler wurde nicht ausgeführt. Soll: Das vor EOF eingetroffene Mausereignis wird noch wirksam, Ergebnis M, Formular entladen.
Ursache: In der modalen Run-Schleife
setzt zustellen einen Handlerframe auf. Direkt danach wird ungeachtet von
dispatched wegen rt.ende zurückgekehrt. Das Ereignis ist bereits aus der
Queue entfernt und wird stillschweigend verloren.
Vertrag: Mausereignisse in Zellenkoordinaten / Reihenfolge bis zur beobachtbaren Handlerausführung; Design D1/D2; Tasks 1.2/2.1. Korrektur: EOF als Ende der Eingabequelle behandeln und bereits angenommene Ereignisse/Handler geordnet abarbeiten, bevor die modale Ausführung endet.
Ursprüngliche weitere Designabweichung
V5 — Gleichzeitig wartende klassische Quellen erhalten eine andere Priorität (mittel)
Reproduktion: KEY(15) ON und UEVENT ON. Vor demselben Zustellpunkt liegen eine passende Taste in der Eingabequeue und ein gemeldeter UEVENT vor. Die Handler hängen K bzw. U an.
Ist: UK. Soll: KU gemäß der bestehenden klassischen Quellpriorität.
Ursache: Vm::zustellen wählt
bereits gemeldete Traps aus, bevor die wartende Taste durch taste_trappen
gemeldet wird. Die Prioritätsauswahl in Traps sieht die Taste deshalb noch
nicht. Früher erfolgte die Tastenprüfung vor der gemeinsamen Trap-Auswahl.
Vertrag: Design / Non-Goals: keine Änderung der festgelegten Priorität gleichzeitig fälliger klassischer Quellen; D1/D2; Task 2.1. Korrektur: Fälligkeitserfassung und Trap-Auswahl so koordinieren, dass die bestehende Quellpriorität erhalten bleibt, ohne die Reihenfolge zwischen Maus- und Tasteneingaben wieder nach Quellarten umzusortieren.
Abdeckung und positive Nachweise
| Delta-Requirement | Nachweis / Einschränkung |
|---|---|
| Ereignisquellen mit Zeit vom Host | Host-Warteschnittstelle, eingefrorene virtuelle Zeit, klassischer Timer und Forms-Timer-SLEEP getestet. Keine reale Rückfalluhr in der VM; Zustellung nach Menüschluss durch V3-Regression abgesichert. |
| Mausereignisse in Zellenkoordinaten | Mapper-/Bounds-Tests, leere Verbraucher, KM/MK-Korpus und gemischte Eingaben. V4-Regressionen sichern EOF in modalen und modellosen Schleifen ab. |
| Abschließende Liste der Zustellpunkte | DOEVENTS-Wert, SLEEP, vorbereitete und erst beim Warten eintreffende INPUT-Ereignisse getestet; V1–V3 geschlossen. |
| Getrappte Tasten verlassen den Eingabestrom | ON/OFF/STOP × INKEY$/INPUT/LINE INPUT/INPUT$, mehrfaches STOP-Merken und Dialogrestpuffer getestet. |
| Signal-Trap auf Betriebssystemsignalen | Beide Kennungen, Maskierung und ungültige Werte getestet. V1-Regression sichert Signalzustellung während blockierender Eingabe ab. |
| Fokus, Tabreihenfolge und Access-Keys | Tab/Shift-Tab, BackTab-Mapper, Access-Keys und einfacher LostFocus→GotFocus-Lauf belegt. V2-Regressionen sichern Control-Argumente und verwandte Objektaufrufe ab. |
| Menüsystem | Menüeigenschaften/-auswahl und Sperre an normalen Grenzen getestet. V3-Regression sichert Freigabe innerhalb von SLEEP ab. |
| Zellenpuffer ohne Terminalabhängigkeit | Separater Workspace kompiliert FRM/VM und liefert KM; 16 Pakete im normalen Dependency-Graph, keines davon crossterm/ratatui/signal-hook. CLI schaltet das Feature ausdrücklich ein. |
| Ereigniszustellung an Anweisungsgrenzen | Bestehende SUB-/GOSUB-/BYREF-/RESUME-Tests und Host ohne erlaubte Uhrabfragen grün. V2/V5-Regressionen sichern zulässige Handlerbeginn-Reihenfolge und klassische Priorität ab. |
Erneut ausgeführt:
cargo test --workspace: 419 bestanden, 0 fehlgeschlagen, 1 ignoriert.openspec validate ereigniszustellung-und-hostgrenzen --strict: gültig.- Isolierter Einbetter mit CaptureHost: KM, Dependency-Prüfung erfolgreich.
- Separate Review-Proben: 6 bestanden, 0 fehlgeschlagen. Die Kontrollprobe prüft Maus unmittelbar vor getrappter Taste.
- Workspace-Ereignistests: 25 bestanden, einschließlich Frist-Watchdog.
- Keine bestehenden Sollausgaben neu aufgezeichnet oder geändert.
Warnings-denied Clippy, Formatprüfungen und Compile-/VM-Benchmarks wurden nach der Behebung erneut erfolgreich ausgeführt; Zahlen siehe verification.md. Kein interaktiver Terminaltest und keine Windows-/Linux-Matrix. Die Proben speisen Ereignisse gezielt über Host ein und benötigen weder echte Signale noch reale Wartefristen.
Review-Proben reproduzieren
Im Repository-Wurzelverzeichnis ausführen. Das erzeugt ausschließlich einen separaten temporären Cargo-Treiber und referenziert den aktuellen Produktcode:
python3 - <<'PY'
from pathlib import Path
import json, subprocess, tempfile
root = Path.cwd()
p = Path(tempfile.mkdtemp(prefix='tb-review-'))
manifest = '[package]\nname="tb-review"\nversion="0.0.0"\nedition="2021"\n[workspace]\n'
manifest += '[[test]]\nname="befunde"\npath=' + json.dumps(str(root / 'openspec/changes/archive/2026-09-05-ereigniszustellung-und-hostgrenzen/review-probes.rs')) + '\n[dependencies]\n'
for name in ['tb-vm', 'tb-runtime', 'tb-ui', 'tb-frontend']:
manifest += name + ' = { path = ' + json.dumps(str(root / 'crates' / name)) + ' }\n'
(p / 'Cargo.toml').write_text(manifest)
subprocess.run(['cargo', 'test', '--manifest-path', str(p / 'Cargo.toml'), '--test', 'befunde', '--', '--nocapture'], check=True, timeout=120)
PY
Alle sechs Proben müssen auf dem korrigierten Stand bestehen. Ihre Erwartungen wurden auch in den regulären Workspace-Testlauf übernommen.