Code Review: Textcounter
Ein simpler CGI - Textcounter
Ausgangscode
Probleme
Folgende einfache Fehler finden wir im Code:
- Zeilen 26,28,34,35,38,41,46,47: Die Fehlervariable $! wird nicht in die Fehlermeldung eingebunden. perldoc perlvar
- Zeilen 28,34,41,46: Das zweite Argument für flock ist ungültig.
- Zeilen 34,46: ein explizites UN-locking ist überflüssig.
Das Script steht weiterhin vor einem logischen Problem: Die Datei wird einmal zum Lesen geöffnet, ein Zählerstand wird eingelesen. Dann wird die Datei wieder geschlossen, um wieder geöffnet zu werden. Der erhöhte Zählerstand wird eingetragen.
Zwar wurde der Versuch gemacht, durch Locking simultane Zugriffe zu vermeiden, aber all dieser Schutz ist hin, wenn die Datei geschlossen wird. Und nach Murphys Gesetzen wird immer dann, wenn die Datei für eine Microsekunde geschlossen ist, ein paralleler Zugriff stattfinden. Das ist in der Tat gar nicht mal unwahrscheinlich, denn wenn ein anderes Programm auf den Zugriff wartet, wird es ihn sofort bekommen, wenn die Datei nicht mehr gelockt ist. Eine Korruption der Daten ist also nicht wirksam unterbunden.
Trotz allem positiv am Code:
- strict ist in Verwendung
- Die Warnungen sind eingeschaltet
- Der Taint-Modus ist aktiviert - sehr gut
- Es wird ein anständiges Template-System (perldoc HTML::Template) verwendet
Ziele
Was sind also die Ziele. Da wären die einfachen:
- Verbesserung der Fehlermeldungen mit $!
- Verwenden der richtigen Argumente für flock
- Vermeiden des expliziten UN-Locking direkt vor dem close()
Aus perlfunc können wir entnehmen, welche Argumente flock() benötigt. Um Plattformunabhängig zu bleiben, verwenden wir die korrekten Konstanten aus Fcntl (perldoc Fcntl).
use Fcntl ':flock'; # ODER require Fcntl; import Fcntl ':flock';
Wir werden uns für die zweite Variante (require und import) entscheiden, da wir die Konstanten nur dann brauchen, wenn flock auf dem System vorhanden ist.
Das Problem mit der Datenkorruption umgehen wir galant, indem wir die Datei nur einmal öffnen: zum Lesen und zum Schreiben. Näheres dazu in perldoc -f open und perldoc perlopentut. Dabei verwenden wir die Funktion seek, um wieder zum Anfang der Datei zu springen und truncate, um den alten Dateiinhalt zu löschen.