- Schritt 3: Debugging eines CGI-Programmes
Bevor ich auf die Standardfehler eingehe, die CGI-Programmierer wiederfahren, erst einmal zu den
Fehlern, die konzeptionell bedingt sind und normalerweise unerwähnt bleiben.
Das obige Beispielprogramm funktioniert und scheint auch keine Probleme zu machen. Dennoch besitzt es
einen Fehler, welches dieses einfache und anscheinend harmlose Programm zur Falle machen kann!
In den meisten Fällen wird dieses Programm keine Probleme machen. Der Webmaster, der es geschrieben hat,
kann sich zurücklehnen und an nichts Böses denken. Und dann, vielleicht nachdem das Programm
mehr als ein Jahr fehlerfrei gelaufen ist, schnappt die Falle zu!
Plötzlich bläht sich die Datendatei auf und sprengt jede Speichergrenze. Bevor dies entdeckt wird,
ist meistens die Festplatte voll, oder aber der Prozessor versinkt ins Nirvana, weil es anscheinend einen
inkonsistenten Prozess bearbeitet.
Was ist geschehen?
Was leider oft vergessen wird, ist, das wir uns bei der CGI-Programmierung auf Systemen bewegen, auf
denen zur selben Zeit mehrere Benutzer arbeiten können, wo also auch viele Prozesse gleichzeitig
nebeneinander laufen.
Beim Absenden der Eingabeform durch einen Besucher der Webseite wird ein Prozess gestartet. Also das
CGI-Programm, welches wir oben entwickelt haben. Falls nur selten Besucher kommen macht dies keine Probleme.
Ab einer bestimmten Besuchsrate jedoch kann es passieren, daß plötzlich 2 oder mehr Prozesse
zur selben Zeit versuchen wollen, auf die Datendatei zu schreiben.
Die Folgen können über die Zerstörung von Daten bis zum Endloslaufen eines Prozesses gehen.
Wenn man also ein CGI-Programm hat, welches auf gemeinsame Objekte (Dateien) zugreift, muß dafür
gesorgt werden, daß keine Synchronisationseffekte auftreten.
Die Informatik liefert hierzu einige gute Lösungsansätze. (Semaphoren, Busy Wait, Monitore, ..) Leider
sind kaum gute Dokumentationen hierzu zu finden, und noch viel weniger konkrete Beispiele. (Anscheinend ist dieses
Problem noch nicht so bekannt geworden, da viele Benutzer noch von altertümlichen Windows-Rechner
ausgehen.)
Der folgende Code zeigt eine relative einfache Möglichkeit, dieses Problem zu lösen:
# Inter values for flock().
$LOCK_SH = 1;
$LOCK_EX = 2;
$LOCK_NB = 4;
$LOCK_UN = 8;
sub lock {
local($fh) = @_;
flock($fh,$LOCK_EX);
# and, in case someone appended
# while we were waiting...
seek($fh, 0, 2);
}
sub unlock {
local($fh)=@_;
flock($fh,$LOCK_UN);
}
|
Wird eine Datei zum Schreiben geöffnet wird die Datei gelockt. Dies hat zur Folge, daß
kein anderer Lesender oder Schreibender Prozess auf diese Datei zugreifen kann; Trifft ein open()
auf eine gelockte Datei, wartet dieses so lange, bis die Datei geunlockt wurde und öffnet erst
dann die Datei.
Nachdem der Prozess, der die Datei gelockt hat, fertig ist, ruft er unlock() auf.
Das obige CGI-Programm sieht dann so aus: (Nur der Teil, der die Datei schreibt)
...
open(filehandle,">>$dateiname")
|| &Fehlermeldung("Kann die Datei $dateiname nicht öffnen!");
&lock(filehandle);
print filehandle "-------Neuer Eintrag-------\n";
print filehandle "Lernerfolg = $in{'Lernerfolg'}\n";
print filehandle "Tempo = $in{'Tempo'}\n";
print filehandle "Vorkenntnisse = $in{'Vorkenntnisse'}\n";
print filehandle "Kommentar: $in{'Kommentar'}\n\n";
&unlock(filehandle);
close filehandle;
print "</HTML>\n";
# Wir schliessen das HTML-Dokument
exit(0);
...
|
Die Subroutinen lock() und unlock() fügen wir wieder am Ende des Programmes an. Oder
wir benutzen eine Library. Doch dazu im nächsten Kapitel.
Standardfehler
Im folgenden zeige ich anhand eines Frage-Antwort-Spieles einige Standardfehler und Lösungen dazu auf.
Diese Fehler kommen immer wieder vor und können sogar Profis wiederfahren. Dieses Frage- und Antwort-Spiel
wurde '96 im Original von Tom Christiansen in Englisch
geschrieben. Ich kopiere nur ein Teil daraus.
- Q:
- Wem gehört das Skript?
- A:
- Mir gehört es.
- Q:
- Welche Dateirechte hat das Skript?
- A:
- Sie waren auf 0600! Aber ich hab gerade bemerkt, daß es so ja nicht ausführbar ist; Ich setz es besser auf 0755.
- Q:
- Liegt das Skript im richtigen Verzeichnis?
- A:
- Nein, ich vergaß, daß ich es ja in das cgi-bin Verzeichnis tun muss.
- Q:
- Unter welcher UID führt der Server ein CGI Skript aus?
- A:
- www. Ups, Es kann dann ja natürlich nicht auf meine Dateien oder Verzeichnisse zugreifen.
- Q:
- Kann die UID, unter dem der Server das Skript ausführt auf alle benötigten Dateien schreiben/lesen?
- A:
- Nein, mir gehören die Dateien und ich hab Rechte auf 0600 gesetzt, anstelle von 0666. Ich glaub
dies ist der Grund, warum es die Dateien nicht öffnen kann?
- Q:
- Was steht in der Error-log des Servers?
- A:
- Ich dachte bisher nicht daran, dort rein zu schauen. Oh, da stehts ja >:)
- Q:
- Welche Perl-Version wird benutzt?
- A:
- Perl, Version 5.002 (perl -v)
- Q:
- Wie lautet der Pfad zum Perl-Interpreter?
- A:
- /local/bin/perl.
- Q:
- Und wie lautet der Pfad in deinen Skript?
- A:
- /usr/bin/perl. Oh, natürlich kann es dort nichts finden.
- Q:
- Hast du versucht in der Newsgroup comp.infosystems.www.authoring.misc, anstelle von comp.lang.perl.*
Fragen zu posten?
- A:
- Nein. Ist das der Grund, warum ich keine gute Antwort und nur Flames bekommen hab?
- Q:
- "If you're running some brain-dead, bondage-and-discipline pseudo-operating system from The Evil Empire, did you bother to read what the Windoze Perl FAQ says about the Web?" (Den konnte ich einfach nicht übersetzen :-))
- A:
- Nein, ich kannte es bisher nicht.
- Q:
- Did you avoid placing an interpreter in your cgi-bin the way you're warned about at
http://www.perl.com/perl/news/latro-announce.html and from CERT?
- A:
- No, what's wrong with it? (noise of disk grinding to dust after corporate secrets stolen heard in the background)
|
|