Mit Hardware-Beschleunigung und schnellem Netz hilft Desktop-Virtualisierung, Administrationsaufwand und Kosten sparen, ADMIN 04/2013 verrät, wie die ... (mehr)

Workaround

Das Skript ist simpel. Der aufmerksame Leser mag sich fragen, wozu Zeile 7 gut ist. Sie umgeht einen Bug bei der Verarbeitung der Timeouts von CGI-Programmen, von dem der Apache Server 2.2.21 mit Prefork-Modul betroffen ist. Wenn ein Programm nämlich auf Stdout und Stderr nichts ausgibt, versucht der Webserver erst nach dem Timeout für Stdout auch Stderr zu lesen. Erst wenn für diese Verbindung auch ein Timeout aufgetreten ist, beendet er die Anfrage. Zeile 7 sorgt dafür, dass nur ein Timeout-Intervall nötig ist. Leider wird damit auch der eigentlich richtige HTTP-Fehlercode 504 verhindert. Stattdessen liefert der Webserver eine leere Antwort.

Das Programm installieren Sie als »burn0.pl« in einem Verzeichnis, das für CGI-Skripte konfiguriert ist. Im Folgenden gehe ich davon aus, dass der Webserver auf »localhost« läuft und der URL-Pfad »/cgi/« auf das CGI-Verzeichnis abgebildet wird.

$ curl http://localhost/cgi/burn0.pl
00:00:00.50023

Die Ausgabe zeigt, wie lange der Datenbankprozess Rechenzeit verbraucht hat. Die gewünschte Dauer übergeben Sie als CGI-Parameter:

$ curl http://localhost/cgi/burn0.pl\?3
00:00:03.000207

In meiner »httpd.conf« ist ein Timeout von 5 Sekunden eingestellt. Läuft die SQL Anfrage 4,9 Sekunden, sollte der Server noch eine vernünftige Antwort liefern, bei 5,1 Sekunden schon nicht mehr.

$ time curl http://localhost/cgi/burn0.pl\?4.9
00:00:04.900198
real    0m4.958s
user    0m0.003s
sys     0m0.006s
$ time curl http://localhost/cgi/burn0.pl\?5.1
curl: (52) Empty reply from server
real    0m5.044s
user    0m0.005s
sys     0m0.005s

Um den eingangs beschriebenen Effekt zu beobachten, rufen Sie »burn0.pl« mit dem Parameter 60 auf. Das Curl-Kommando ist nach 5 Sekunden fertig; dem Datenbankprozess können Sie aber eine volle Minute bei der Arbeit zusehen.

Abhilfe

Der umsichtige Programmierer sollte also irgendwas unternehmen, damit beim Eintreffen des SIGTERM nicht nur das CGI-Programm beendet wird, sondern auch der Datenbankprozess. Eine Variante wäre, den Prozess einfach zu killen. Da PostgreSQL für jeden Benutzer einen separaten Prozess startet, ist das gleichwertig mit dem Abbruch der aktuellen Transaktion. Dabei sind drei Probleme zu lösen:

  • das SIGTERM muss zeitnah behandelt werden
  • die PID des Datenbankprozesses muss gefunden und
  • er muss beendet werden.

Als Lösung für das erste Problem denkt ein erfahrener Perl-Programmierer wahrscheinlich sofort an »$SIG{TERM}« . Leider funktioniert das hier nicht, denn moderne Perl-Versionen stellen asynchrone Signale nur an sicheren Punkten im Programm zu. Mitten im Aufruf einer C-Funktion ist aber kein solcher Punkt. Der Handler wird also erst aufgerufen, wenn »$sth->execute« in Zeile 13 zurückkehrt. Mit »POSIX::sigaction« kann der Signal-Handler so installiert werden, dass das Signal zeitnah zugestellt wird.

Ähnliche Artikel

comments powered by Disqus
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Ausgabe /2023