Die/exit ignorieren und klasse unloaden

Guten Tag liebe community...
Ich bin gerade dabei mir ein php-basiertes "Betriebssystem" zusammenzubauen. Angefangen habe ich damit eigentlich nur um Linux besser verstehen zu können und an die Grenzen von PHP vorzudringen, jetzt ist es jedoch zu einer Art Spaßprojekt mutiert. Bis jetzt funktioniert alles schön und gut, nur habe ich zwei meiner Meinung nach etwas andere Fragen...

Frage Nummer eins: Gibt es eine Möglichkeit, ein die() oder exit() zu ignorieren, außer das Ganze in einer Sandbox laufen zu lassen? Denn wenn der Kern ein Programm (eine Klasse mit mindestens den Methoden run,close und signal) ausführt, kann im Programm einfach exit() aufgerufen werden und das wars mit dem tollen Betriebssystem ^^
Meine einzige Idee dazu (kam mir gerade beim Schreiben) wäre register_shutdown_function(). Die shutdown-funktion wird ja vor dem Ende des scriptes (bzw. währenddessen) aufgerufen. Wenn von dort aus einfach das "böse" programm gekillt wird könnte der kernel seine Aufgabe von der shutdown-funktion aus fortführen und wäre von einem Exit unbetroffen. Das würde meiner Meinung nach gehen, da diese funktion ja vor dem "zerstören" der objekte geschieht. Problem bei der Sache: Wie bringe ich den Kern dazu das Script an genau der selben Stelle fortzuführen wie die an der das exit() aufgerufen worden ist?
Eine weitere Idee wäre (wieder beim Schreiben gekommen...) den Programmcode zu laden, alle exit() und die() via Regex rauszufiltern ($func = "exit"; $func(); funktioniert nicht, da exit und die Sprachkonstrukte und keine Funktionen sind => Arbeit simpler) und dann per eval (jaja, eval is evil, ermöglicht es aber z.b. nach fatal errors in den ausgeführten scripten das eigentliche script (bei mir der kernel..) unbehelligt weiter zu verwenden) auszuführen. Wenn das euerer Meinung nach die bessere Methode ist, wie müsste die Regex aussehen (nicht so meins, gerade erst angefangen das Thema durchzumachen)?
Das war die wichtigere der beiden Fragen.

Frage Nummer zwei wäre: Gibt es eine Möglichkeit einmal geladene klassen on the fly wieder "unzuloaden"? Das wäre nämlich wichtig, weil sich der Kernel seine Klassen quasi selbst zusammenbasteln können soll aus allen benötigten Modulen. Bisher mache ich das so, dass die Module einfach eigene Klassen (z.b. kernelModule_threading) sind, von welchen alleine der Kernel genau ein Objekt besitzen darf. Dann hat die Kernel-klasse die magische Methode __call(), damit aufrufe alá kernel()->writeFile(); möglich sind (kernel() ist eine Funktion die immer die gleiche instanz des kernels zurückgibt). Das ist mir aber zu langsam auf Dauer, da jede einzelne modulmethode dann über kernel()->... aufgerufen werden muss (da die benötigte Funktion ja in einem anderen Modul angesiedelt sein könnte) was zu vielen unnötigen Funktionsaufrufen führt und somit langsam ist... Auch gibt es ja nichts mehr, was man mit den alten Modulen die vielleicht sogar schon ersetzt wurden (das System sollte nicht rebootet werden müssen, auch wenn der ganze Kern ausgetauscht wird) tun könnte...
Nun soll der Kernel genau eine Klasse aus dem Code der einzelnen Module "bauen" (kernel_moduleClass z.b.), die alte kernel_moduleClass löschen und durch die neue überschreiben (eval is evil, ich weiß ^^... aber hier isses nützlich), da ich eine solche Methode einfach für näher (wahrscheinlich eh darüber -.-) an den Grenzen, welche ich ja finden möchte, sowie bei vielen geladenen Modulen und vielen Modulfunkttionsaufrufen für schneller halte.

PS: Ich möchte jetzt nicht Sachen wie "das ist sinnlos", "in C geht das", "was bringt dir das?" oder ähnliches hören, denn ich weiß, dass es keinen praktischen Nutzen hat. Wohl aber lerne ich dadurch... Ich habe bereits ein webOs, welches ich auch ständig weiterentwickle und welches mittlerweile doch schon recht stabil und schön läuft. Auch dieses Projekt möchte ich mit meinem neu gewonnenen Wissen bereichern...


Ich hoffe dieser ellenlange Text hat jetzt nicht zu viele Leute verscheucht...
 
Zu Frage 1:
Wenn ich Dich richtig verstehe, geht es um auftretende Fehler im laufenden System?
Da kannst Du nur was gegen tun, wenn Du alles sorgfältig testest und die fehler behebst! Ein try und catch Konstrukt, wie bei C++ kenne ich für PHP jedenfalls nicht.
Wenns doch sowas gibt, wäre das Deine Lösung, denke ich.

Zu Frage 2:
Da PHP serverseitig läuft, kannst Du Module so ohne weiteres nicht "unloaden", wie Du es nennst. Die aktuelle Seite muß neu geladen werden und en Parameter entscheidet, ob und welche Module geladen werden oder nicht!

So denke ich zumindest, wenn ich das mal nur so überfliege...
;-)

EDIT:
Hab grad noch mal gesucht und festgestellt, es gibt doch ein try/catch Konstrukt für PHP.
 
Zuletzt bearbeitet:
ja, try/catch gibts für PHP, jedoch behandelt dieses nur exceptions... Fatale fehler und so führen trotzdem noch zum Beenden des scriptes. Das ist allerdings nicht mein Problem, die Programme werden sowieso mit eval() ausgeführt (habe meine Gründe dafür)... Mir gehts eher darum dem Programm nicht zu erlauben das ganze script zu killen, und zwar durch z.b. ein einfaches die(); oder exit();
Geplant habe ich alle potentiell schädlichen funktionen im script mithilfe einer auf regex aufbauenden kernel-modul-funktion durch die sichere kernel-version zu ersetzen...
Die beiden (die() und exit()) zu löschen wäre nicht das problem, allerdings kann es ja sein dass ein programm nur
echo "die();" machen will, wo dann das die() gelöscht und durch kernel()->endThisProgram(); ersetzt wird.
Mir fallen jetzt spontan diese möglichkeiten ein ein solches "konstrukt" aufzurufen (am beispiel exit):
exit();
exit(1);
exit($variable);
exit("string");
eval("exit();"); <- Das ist kein problem, da eval() durch kernel()->runUnsaveProgramCode(); ersetzt wird und der übergebene string nochmal von der parser-funktion gesichert.
Bei funktionen wie file_put_contents() (exit und die sind sprachkonstrukte wie echo) kann zusätzlich noch folgendes verwendet werden:
$funktion = "file_put_contents";
$funktion(); <- resultiert in aufruf von file_put_contents();

Mein Problem ist jetzt das alles rauszufiltern...


achja, und das ding läuft direkt in der Konsole, deswegen kein seiten-reload...
 
Hi, also für das Filtern ist es definitiv am besten nicht auf Regex zurückzugreifen (viel zu fehleranfällig bei Zeichenketten etc.) sondern einfach den Tokenizer von PHP zu verwenden:
PHP:
$code = '...'; // Der eingelesene PHP Code
$result = '';

foreach(token_get_all($code) as $token)
{
  if(is_array($token))
  {
    if($token[0] == T_EXIT)
    {
      // Hier kann dann eine Ersetzung vorgenommen werden.
    }
    else
    {
      $result .= $token[1];
    }
  }
  else
  {
    $result .= $token;
  }
}

eval($result);
 
Zurück