xwolf.de|com

Menü

Inhalt dieser Site

Ansicht

Individuelle Benutzerkonfiguration für die Site.

Druckansicht Startseite Suchen

A A A A

CGI Tutorial - Teil 6 / 10

Wolfgang Wiese (www.xwolf.de, xwolf@xwolf.de), Juli 1998, Letzte Änderung: Mai 2003

[Das Common Gateway Interface]
[Übergabe von Benutzereingaben]
[Decodierung der übergebenen Daten]
[Schritt 1: Erstellung einer Eingabeform]
[Schritt 2: Die Programmierung]
[Schritt 3: Debugging eines CGI-Programmes]
[Standardfehler]
[Die Optimierung von CGI-Programmen durch Libraries und Module]
[Tipps, Tricks und Beachtenswertes]
[Links zu wichtigen FAQs und CGI-Seiten]

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 Sie sich das nicht vorstellen können, denken Sie einfach mal an eine Diskussionsrunde, wo ein Protokollant alles mitnotiert. Plötzlich wird die Diskussionsrunde hitziger und anstelle, daß nur einer redet, sprechen plötzlich zwei oder mehr Leute durcheinander. Folge: Der Protokollant wird sich mehrfach verschreiben, nicht mehr mitkommen, wahrscheinlich einige Sätze falsch aufschreiben und durchstreichen oder den ganzen Zettel rausreissen und zerknüllen.
Und irgendwann wird er einfach aufgeben und es lassen alles niederzuschreiben, oder aber seinen Schuh ausziehen und so lange auf den Tisch vor ihn eindreschen, bis wieder Ruhe ist...

Wenn man also ein CGI-Programm hat, welches auf gemeinsame Objekte (Dateien) zugreift, muß dafür gesorgt werden, daß keine gleichzeitigen schreibenden Zugriffe auf Dateien geschehen können.
Die Informatik liefert hierzu einige gute Lösungsansätze. (Die Stichworte lauten: Semaphoren, Busy Wait, Monitore, ..) Leider sind kaum gute, allgemeinverständliche Dokumentationen hierzu zu finden, und noch viel weniger konkrete Beispiele. (Anscheinend ist dieses Problem noch nicht so bekannt geworden, da viele Benutzer noch von Einzelplatzrechnern ausgehen.)
Der folgende Code zeigt eine relative einfache Möglichkeit, dieses Problem unter Perl (auf Unix- oder Linux-Systemen!!) 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 bzw. ein Modul. Doch dazu im nächsten Kapitel.
(Anmerkung zu flock(): Bitte beachten Sie, daß es selbst mit der sauberen Benutzung von flock() unter Unix zu Zugriffskonflikten kommen kann, wenn der Webserver und das CGI-Programm auf unterschiedlichen Partitionen liegen. flock() verhält sich über Mounting Points instabil. Anstelle flock() alleine, sollte man dieses deshalb ggf. mit Softwarelinks verknüpfen.
Unter Windows ist flock() leider fast völlig untauglich.)



Info

© 1996 - 2003 by xwolf