Instanzmanager Stufe 3: Prozessaufsicht, Start und Stopp (#528)
Der Anlass des ganzen Vorhabens: Am 2026-09-08 hat sich eine Instanz aufgehaengt und wurde von Windows beendet. Zu diesem Vorgang steht keine einzige Zeile in den Instanzprotokollen, kein Bugtracker-Eintrag, kein Watchdog-Alarm - weil Meldeweg und Watchdog in genau dem Prozess lebten, ueber den sie haetten berichten sollen. Ab jetzt sieht jemand anders hin. Neu ist ClawdDotNet.Manager mit genau EINEM Projektverweis: Core. Das ist keine Sparsamkeit, sondern die halbe Architektur - App schleppt sechzehn Werkzeugprojekte hinter sich her, und "keine Werkzeuge im Manager" soll eine Eigenschaft des Bauplans sein und keine Absichtserklaerung. DIE ENTSCHEIDUNG, AN DER ALLES HAENGT: Die Aufsicht fragt den Socket, nicht die Prozessliste. Die Prozessliste sagt, dass etwas da ist. Sie sagt nicht, ob es noch arbeitet - und genau das war der Zustand, den niemand bemerkt hat. Ein Durchgang kennt drei Antworten: Socket antwortet, sie laeuft. Socket schweigt und der Prozess ist weg, Absturz mit Abschiedscode. Socket schweigt und der Prozess lebt, verstummt - aber erst nach mehreren Fehlversuchen in Folge, denn ein Alarm bei jedem Aussetzer ist nach einer Woche der Alarm, den niemand mehr liest. Ein Start gilt erst, wenn die Instanz antwortet. Zwischen "der Prozess laeuft" und "die Instanz laeuft" liegen Datenbank, Agenten und Kestrel; wer nur auf Process.Start wartet, haelt eine Instanz fuer gestartet, die gleich an einer kaputten Konfiguration scheitert. Angehalten wird durch Bitten. Neu auf der Instanzseite: POST /api/instanz/beenden, ausschliesslich ueber den Socket - ueber TCP gibt es den Endpunkt nicht, auch mit gueltigem Token nicht, und er antwortet dort 404 statt 403. Die Lebensdauer einer Instanz gehoert dem Manager; eine Browsersitzung soll den Prozess, der sie bedient, nicht beenden koennen. Ausgeloest wird der Wunsch erst nach dem Absenden der Antwort (Response.OnCompleted), sonst bekaeme der Manager statt einer Zusage einen Verbindungsabbruch und hielte ihn fuer einen Fehlschlag. Wiederfinden nach einem Managerausfall (E-M6): Die Zustandsdatei instance-state.json ist der Hinweis, der Socket ist der Beweis. Erst wird gefragt, wer da antwortet; nur bei gleicher Instanzkennung wird die Prozesskennung aus der Datei angefasst. Andersherum fuehrt eine wiederverwendete Nummer nach einem Neustart der Maschine geradewegs dazu, ein fremdes Programm zu beaufsichtigen und beim Anhalten zu beenden. Selbsttaetiger Neustart ist bewusst NICHT gebaut. Die Abnahmebedingung lautet "merkt es und meldet es", und zum Neustarten trifft das Konzept keine Entscheidung; eine Instanz in einer Schleife wieder hochzufahren, die jedes Mal abstuerzt, waere die falsche Vorgabe fuer etwas, das niemand entschieden hat. Als offene Frage aufgeschrieben. ABNAHME, mit echten Prozessen gemessen: Manager startet Instanz Test in 0,7 s, identifiziert sie ueber die Named Pipe, schreibt die Zustandsdatei (pid 54476, id d68af6fd). Prozess von aussen abgeschossen. Naechster Durchgang: Crashed, Code -1, meldenswert, Zustandsdatei weggeraeumt. Dazu 20 Tests gegen gesteuerte Prozesse - ein Absturz zum gewuenschten Zeitpunkt und eine wiederverwendete Prozesskennung sind mit einem echten Programm nicht herzustellen. Noch offen in dieser Stufe: Instanzen anlegen, Lizenz im Manager, Sub-Token je Instanz, und der Managerprozess selbst. Build ohne Warnungen, 737 Tests gruen, 8 uebersprungen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -282,6 +282,14 @@ startet sie und gibt ihr den Socketpfad mit; die Instanz verbindet sich einmal
|
||||
zurück und beendet sich, wenn das nicht gelingt. Kein Selbstzweck-Handschlag,
|
||||
sondern die Prüfung aus E-M3.
|
||||
|
||||
**Startet der Manager eine abgestürzte Instanz wieder?** Bisher nicht — er merkt es und
|
||||
meldet es, mehr nicht. Dafür spricht, dass eine Instanz, die nachts um drei abstürzt, bis
|
||||
zum Morgen tot bleibt. Dagegen spricht die Schleife: Eine Instanz, die an einer kaputten
|
||||
Konfiguration scheitert, stürzt beim zehnten Versuch genauso ab wie beim ersten, und dann
|
||||
hat man statt einer toten Instanz eine tote Instanz und ein volles Protokoll. Wenn es
|
||||
kommt, dann mit Wartezeitverdopplung und einer Obergrenze, nach der er es sein lässt und
|
||||
das meldet.
|
||||
|
||||
**Der Aufhänger aus 1.1 ist nicht geklärt** (#529). Er verschwindet mit dem
|
||||
Umbau vermutlich von selbst, weil es den Selbst-Neustart nicht mehr gibt — aber
|
||||
„vermutlich" ist kein Befund. Zwei unbelegte Verdachtsmomente: `BackupScheduler`
|
||||
@@ -313,7 +321,7 @@ Verbindung und führt sie zusammen, mit der Instanzkennung an jedem Ereignis.
|
||||
|---|---|---|
|
||||
| 1 ✔ | Einstellungen und Protokolle je Instanz trennen (Abschnitt 6) | Zwei Instanzen gleichzeitig, keine schreibt der anderen ins Protokoll |
|
||||
| 2 ✔ | Instanzprozess kopflos lauffähig, Kestrel auf dem Socket | Eine Instanz läuft ohne Fenster, der Socket antwortet |
|
||||
| 3 | Manager: anlegen, starten, anhalten, Prozessaufsicht, Lizenz, Sub-Token | Eine Instanz abschießen — der Manager merkt es und meldet es |
|
||||
| 3 ◑ | Manager: anlegen, starten, anhalten, Prozessaufsicht, Lizenz, Sub-Token | Eine Instanz abschießen — der Manager merkt es und meldet es |
|
||||
| 4 | Weboberfläche zieht um, Weiterleitung, ein Ereignisstrom | Eine Adresse, ein Zugang, Wechsel ohne Neustart |
|
||||
| 5 | Instanzfenster als eigener Prozess, Wechsel holt das Fenster nach vorn | Kein Neustart mehr beim Wechseln |
|
||||
| 6 | Sicherungen im Manager (falls Abschnitt 7 dafür entscheidet) | Zurückspielen hält die Instanz an und startet sie wieder |
|
||||
@@ -399,3 +407,65 @@ Aufräumen beim Beenden) sind unter Windows gegenstandslos und werden dort mit B
|
||||
ungeprüft, obwohl er die Zielplattform ist. Und das geordnete Ende auf `SIGTERM` ließ sich
|
||||
hier nicht auslösen: Windows kennt das Signal für einen fensterlosen Prozess nicht.
|
||||
Beides gehört auf die Linux-Testmaschine.
|
||||
|
||||
### 9.3 Was Stufe 3 bisher gebracht hat
|
||||
|
||||
**Die Aufsicht steht, Lizenz und Sub-Token fehlen noch.** Neu ist das Projekt
|
||||
`ClawdDotNet.Manager` mit genau **einem** Projektverweis: `ClawdDotNet.Core`. Das ist
|
||||
keine Sparsamkeit, sondern die halbe Architektur — `ClawdDotNet.App` schleppt sechzehn
|
||||
Werkzeugprojekte hinter sich her, und „keine Werkzeuge im Manager" soll eine Eigenschaft
|
||||
des Bauplans sein und keine Absichtserklärung. Damit `InstanceDirectoryManager` von beiden
|
||||
Seiten erreichbar ist, ist er nach `Core/Instances` gezogen; dorthin gehört er ohnehin,
|
||||
denn er beschreibt, wie eine Instanz auf der Platte liegt.
|
||||
|
||||
**Der Socket ist die Auskunftsquelle, nicht die Prozessliste.** Das ist die eine
|
||||
Entscheidung, an der alles hängt. Die Prozessliste sagt, *dass* etwas da ist — sie sagt
|
||||
nicht, ob es noch arbeitet, und genau das war der Zustand aus 1.1: Die Anwendung stand
|
||||
einwandfrei in der Prozessliste, bis Windows sie als „reagiert nicht mehr" beendet hat.
|
||||
Ein Aufsichtsdurchgang fragt deshalb den Socket und kennt drei Antworten:
|
||||
|
||||
| Socket | Prozess | Befund |
|
||||
|---|---|---|
|
||||
| antwortet | — | läuft |
|
||||
| schweigt | ist weg | **Absturz**, mit Abschiedscode |
|
||||
| schweigt | lebt | **verstummt** — nach genügend Fehlversuchen in Folge |
|
||||
|
||||
Nicht beim ersten Aussetzer: Eine einzelne verpasste Antwort ist Alltag, und ein Alarm bei
|
||||
jedem Aussetzer ist nach einer Woche der Alarm, den niemand mehr liest.
|
||||
|
||||
**Ein Start gilt erst, wenn die Instanz antwortet.** Zwischen „der Prozess läuft" und „die
|
||||
Instanz läuft" liegen Datenbank, Agenten und Kestrel. Wer nur auf `Process.Start` wartet,
|
||||
hält eine Instanz für gestartet, die gleich an einer kaputten Konfiguration scheitert.
|
||||
|
||||
**Angehalten wird durch Bitten, nicht durch Schießen.** Neu auf der Instanzseite:
|
||||
`POST /api/instanz/beenden`, **ausschließlich über den Socket** — über TCP gibt es den
|
||||
Endpunkt nicht, auch mit gültigem Token nicht, und er antwortet dort mit 404 statt 403.
|
||||
Die Lebensdauer einer Instanz gehört dem Manager; eine Browsersitzung soll den Prozess,
|
||||
der sie bedient, nicht beenden können. Erst nach Ablauf der Frist wird hart beendet.
|
||||
|
||||
**Wiederfinden nach einem Managerausfall (E-M6).** Die Zustandsdatei
|
||||
`<Instanz>/instance-state.json` ist der *Hinweis*, der Socket ist der *Beweis*: Erst wird
|
||||
gefragt, wer da antwortet, und nur wenn dieselbe Instanzkennung zurückkommt, wird die
|
||||
Prozesskennung aus der Datei überhaupt angefasst. Andersherum — Prozess suchen, finden,
|
||||
für die eigene Instanz halten — führt nach einem Neustart der Maschine geradewegs dazu,
|
||||
ein fremdes Programm zu beaufsichtigen und beim Anhalten zu beenden. Startzeit und
|
||||
Prozesskennung zusammen entlarven eine wiederverwendete Nummer.
|
||||
|
||||
**Selbsttätiger Neustart ist bewusst nicht gebaut.** Die Abnahmebedingung lautet „merkt es
|
||||
und meldet es", und zum Neustarten trifft dieses Papier keine Entscheidung. Eine Instanz
|
||||
in einer Schleife wieder hochzufahren, die jedes Mal abstürzt, wäre die falsche Vorgabe
|
||||
für etwas, das niemand entschieden hat. **Das ist eine offene Frage** — siehe Abschnitt 7.
|
||||
|
||||
**Abnahme, mit echten Prozessen gemessen.** Der Manager hat die Instanz `Test` in 0,7 s
|
||||
gestartet und über die Named Pipe identifiziert, die Zustandsdatei geschrieben
|
||||
(`pid=54476`, `id=d68af6fd`), dann wurde der Prozess von außen abgeschossen. Der nächste
|
||||
Durchgang meldete `Crashed`, Abschiedscode −1, meldenswert, und räumte die Zustandsdatei
|
||||
weg. Dazu 20 Tests gegen gesteuerte Prozesse — ein Absturz zum gewünschten Zeitpunkt und
|
||||
eine wiederverwendete Prozesskennung sind mit einem echten Programm nicht herzustellen.
|
||||
|
||||
**Ein Hinweis zur Messumgebung.** Die Abnahme lief über einen eigens gebauten Treiber
|
||||
außerhalb der Werkzeugumgebung. Ein Prozess, den ein Agentenwerkzeug hier startet, landet
|
||||
in einem Job-Objekt, das seine Kinder sofort mitnimmt; der Instanzprozess starb dadurch,
|
||||
bevor er die erste Protokollzeile schreiben konnte. Das ist ein Artefakt der Umgebung und
|
||||
keine Eigenschaft des Managers — aber es heißt, dass ein Abnahmetest dieser Art nicht in
|
||||
die gewöhnliche Testreihe gehört.
|
||||
|
||||
Reference in New Issue
Block a user