XShutdown hat mich viele Stunden angestrengten Denkens gekostet, weil es wirklich
nirgendwo dokumentiert ist, was während des normalen Systemabschlusses geschieht.
Normalerweise kennt OS/2 zwei verschieden Systemabschluß-APIs:
- DosShutdown schließt nur alle geöffneten Dateien, schreibt
die Dateisystem-Puffer zurück und löst alle Dateisysteme; das passiert nach dem
Drücken von Strg-Alt-Entf (Ctrl-Alt-Del). Anwendungen werden nicht
ordnungsgemäß geschlossen,
und die WPS wird auch nicht gesichert.
- WinShutdownSystem ist eine API, die zum Presentation Manager
gehört und alle Fenster schließt, die WPS sichert und schließlich DosShutdown
aufruft. Dies ist die normale Systemabschluß-Prozedur: Sie wird ausgeführt,
wenn Sie "Systemabschluß" aus dem Kontextmenü des Desktops oder die entsprechenden
Symbole aus der Klickstartleiste oder dem WarpCenter auswählen.
Das Problem ist, daß es keine Funktion "zwischen" diesen beiden gibt. Wenn Sie
DosShutdown aufrufen, wird die WPS nicht gesichert,
und bei WinShutdownSystem
legt der normale Systemabschluß los, ohne daß man irgendeine Möglichkeit hätte,
noch einzugreifen.
Das bedeutete, daß ich quasi ein komplett neues WinShutdownSystem programmieren
mußte, das hier jetzt erklärt wird. Dies war ziemlich schwierig, da IBM kaum irgendetwas
darüber erklärt, was wirklich während WinShutdownSystem passiert.
Hinweis: In XFolder benutzen der "Erweiterte Systemabschluß" und "WPS
neustarten" denselben Code; der einzige Unterschied sind die Aktionen, die nach dem
Schließen aller Fenster ausgeführt werden. Deshalb werde ich den Begriff "XShutdown"
in den folgenden Erklärungen für beide benutzen, wenn nicht anders angegeben.
XShutdown ist in die WPS integriert und ist sehr stark von
den XFolder-Ersatzklassen abhängig. Bewußt habe ich den XShutdown-Code
nicht einer separaten .EXE-Datei mitgeliefert: zum einen braucht XShutdown Zugriff
auf WPS-interne Daten, die nur durch SOM erreichbar sind; zum zweiten will
ich die Leute davor bewahren, XShutdown ohne installierte XFolder-Klassen
zu starten, da dies die WPS beschädigen könnte. Genauer gesagt benötigt XShutdown
die Klasse XFldObject und den XFolder-Worker-Thread, die die WPS-internen Daten
zugänglich machen.
Um zu verstehen, was XShutdown tut, muß man wissen, wie die
WPS ihre Objekte intern verwaltet. Jedes einzelne Objekt, das
zu einem Zeitpunkt für die WPS relevant wird, sei es durch Bevölkern eines Ordners,
durch Abfragen der Einstellungen oder durch Starten eines Programmes oder
durch was auch immer, wird -- in WPS Terminologie -- vom System "aufgeweckt"
("awakened"); das bedeutet, daß es als SOM-Objekt im Speicher existiert.
Die WPS schläfert nur selten wache Objekte wieder ein, was die Freigabe
des damit verbundenen Speichers und einer Sicherung der Daten des Objekts auf
Festplatte zur Folge hätte.
Das hat zwei Konsequenzen:
- Es gibt immer mehr "wache" Objekte auf Ihren System, als Sie in diesem
Moment annehmen würden, da die meisten von ihnen gerade nicht sichtbar sind.
Sogar wenn Sie einen Ordner geschlossen haben, bleiben die Objekte darin wach;
das beschleunigt das Bevölkern des Ordners, wenn er zum zweiten Mal geöffnet
wird. Das führt dazu, daß die WPS mit jedem Ordner, der geöffnet wird,
immer mehr und mehr Speicher belegt. (Wenn Sie von XShutdown eine Logdatei
erstellen lassen, können Sie sehen, wie viele wache Objekte von XShutdown
gesichert werden; normalerweise sind das einige hundert Objekte, auch wenn
XShutdown nicht alle Objekte sichert, sondern nur die Ableitungen von WPFolder
und WPAbstract. Unter dem Reiter "Interna" im Einstellungsnotizbuch des
Arbeitsoberfläche können Sie sehen, wie viele Objekte derzeit wach sind.)
- Eine Änderung der Objekt-Daten aktualisiert manchmal nur das SOM-Objekt im
Speicher, wird aber nicht auf Festplatte oder in OS2.INI / OS2SYS.INI gespeichert.
Darum gerät die WPS manchmal ins Schleudern, wenn Sie größere Änderungen durchgeführt
haben, wie das Bewegen eines Ordners, der viele abstrakte Objekte enthält, und
danach nicht richtig herunterfahren: die physikalischen Daten auf der Festplatte
und die WPS-Einträge unterscheiden sich dann.
Dafür braucht XShutdown die Klasse XFldObject, die WPObject ersetzt.
Jedes mal, wenn ein Objekt aufgeweckt wird, ruft die WPS diverse Methoden auf
(darunter wpInitData und wpObjectReady).
XFldObject ersetzt diese und übergibt die Speicheradresse des Objekts an den
Worker-Thread, der dann die XFolder-interne Liste aller momentan wachen
Objekte aktualisiert. Soweit ich weiß, gibt es keinen anderen Weg herauszufinden,
welche Objekte gerade wach sind; auf jeden Fall gibt es auch keine dokumentierte
API, die diese Objekte auflisten könnte.
Wenn XShutdown nun aufgerufen und bestätigt wird, startet es
als erstes für die folgende Systemabschluß-Prozedur zwei neue Threads, die
parallel zu den regulären WPS-Threads laufen; der
Haupt-"Systemabschluß-Thread" mit der Nachrichtenschlange für
das Status-Fenster, und der "Update-Thread",
der die OS/2-Fensterliste überwacht und Nachrichten an den Hauptthread
absetzt, wenn das Status-Fenster aktualisiert werden muß.
Daher ist das Schließen aller momentan geöffneten Fenster ein kompliziertes
Zusammenspiel dieser beiden Threads:
Der Systemabschluß-Thread schließt ein Fenster und geht dann so lange in
den Leerlauf, bis der Update-Thread eine Änderung in der Fensterliste meldet
(was bedeutet, daß erfolgreich geschlossen wurde) und den
Systemabschluß-Thread benachrichtigt, der dann wiederum das nächste Fenster schließt,
bis kein Fenster mehr übrig ist.
Nachdem alle Fenster geschlossen worden sind, beendet sich der Update-Thread.
Jetzt geht der Systemabschluß-Thread die Liste aller momentan wachen
Objekt durch (s.o.) und zwingt sie durch den Aufruf der
wpSaveImmediate-Methode, ihre Daten in die INI-Dateien oder auf
Festplatte zu schreiben.
Dies geschieht nur für die Ableitungen von WPAbstract und WPFolder, weil
nach meiner Erfahrung alle anderen Klassen ihre Daten direkt speichern.
(Ich habe einmal versucht, alle Ableitungen von WPFileSystem zu sichern,
und dies verursachte jede Menge Erweiterter Attribute für jede
einzelne Datei, die jemals von der WPS geweckt wurde. Abgesehen davon dauert
der Systemabschluß dann ewig lange.)
Zuletzt, je nach dem welche Aktion gewünscht wird, führt der
Systemabschluß-Thread folgendes aus:
- Wenn Sie "WPS neustarten", ausgewählt haben,
ruft der Systemabschluß-Thread einfach nur DosExit(EXIT_PROCESS, 0)
auf. Da XFolder Teil des Workplace-Prozesses ist und die gesamte WPS in diesem
einen Prozeß läuft (der zweiten Instanz von PMSHELL.EXE),
beendet dies die komplette Workplace Shell. Der Shell-Prozeß (die erste
Instanz von PMSHELL.EXE) startet dann die WPS automatisch neu.
- Wenn Sie "Systemabschluß" und "Rechner neu starten"
ausgewählt haben, speichert XShutdown auch die INI-Dateien.
Das ist nötig, weil DosShutdown, das anschließend aufgerufen wird,
diese nicht sichert.
(Wahrscheinlich deshalb, weil die APIs für INI-Dateien zum Presentation Manager
gehören.) Da die INI-APIs es verbieten, einfach die User- und
System-Profile zu schließen (was die Daten aller anderen Profile auf Festplatte sichern
würde), kopiert XFolder sie in zwei temporäre Dateien, löscht die
Originale, und benennt dann die temporären um.
Nach DosShutdown ("Löse Dateisysteme...") wird das System mit
einem Aufruf des Gerätetreibers DOS.SYS neu gestartet.
Diese Funktion ist in EDM/2 Band 5, Ausgabe 9
beschrieben.
- Wenn Sie "Systemabschluß" OHNE "Rechner neu starten"
ausgewählt haben, schaltet XShutdown nach DosShutdown
die Fensterliste ab und blockiert das System einfach durch einen Aufruf von
DosEnterCritSec und einer unendlichen Schleife. Da alle Dateisysteme
geschlossen sind, sollte keine andere Aktion außer dem Ausschalten oder Neustarten
des Rechners mehr möglich sein.