Apache Prozesse - Zusammenhang

Dadurch das eine IPC-Verbindung per Unix-Socket zwischen zwei Server-Prozessen besteht, kann der Eine nicht ohne den Anderen sterben. Erst wenn beide Sterben wollen (z.B. wegen Timeout, o.ä.) tun sie es auch.
Mit Verlaub, das ist technisch nicht korrekt. Eine Verbindung zu einem Unix-Socket ist aus Prozess-Sicht nichts weiter als ein Eintrag in der Dateideskriptor-Tabelle für diesen Prozess. Umgekehrt wird ein Schuh draus: Ein Kindprozess erbt beim forken vom Eltern-Prozess u. a. die offenen Dateideskriptoren. Solange einer der beiden Prozesse noch lebt, besteht der Unix-Socket weiterhin. Trotzdem kann einer der beiden Prozesse terminieren (entweder durch ein Signal, oder durch eigene Logik, die zu einem exit() führt), ohne dass der andere dabei draufgehen muss.

Wäre es wie von Dir beschrieben, müssten auch Verbindungen vom Typ AF_INET oder AF_INET6 dazu führen, dass Client- und Serverprozess nur gemeinsam beendet werden können. Dass dem nicht so ist, hat jeder vermutlich schon selbst feststellen dürfen :-)
 
Prinzipiell hat Du recht wenn es nur um den Unix-Socket gehen würde.
Aber ich habe - zugegebener Masse zu kurz darauf Eingegangen - von einer IPC-Verbindung gesprochen (Inter-Process-Communication). Damit meine ich die Kommunikation zwischen mod_fcgid und fcgid selbst. Sie wird nur i.d.R. über einen Unix-Socket aufgebaut. Theoretisch gibt es noch andere Möglichkeiten der IPC wie z.B. TCP-Socket, Named-Pipes oder Mutexs .

Apache-Clients werden vom Parent-Prozess lediglich über ein TERM-Signal (also ein "Bitte beende Dich bei Zeiten") aufgefordert sich zu beenden.
Welches der Child aber nicht tut, weil er sich sagt: "Momentchen, ich habe da noch einen offenen IPC."
Es wäre in den meisten Installationen sinnvoll, wenn mod_fcgid das TERM per IPC auch an den fcgid durch reichen würde. Auf der anderen Seite macht es auch Sinn dies nicht zu tun, da fcgid theoretisch ein eigener Server ist und nicht nur von einem Apache-Child abhängig sein muss.

huschi.
 
Aber ich habe - zugegebener Masse zu kurz darauf Eingegangen - von einer IPC-Verbindung gesprochen (Inter-Process-Communication). Damit meine ich die Kommunikation zwischen mod_fcgid und fcgid selbst.
IPC ist im weiteren Sinne alles, was die Kommunikation zwischen Prozessen erlaubt. Im engeren Sinne wird IPC oft für die System V IPC-Mechanismen (Shared Memory, Semaphores & Co) als Synonym verwendet. Bei FastCGI kommen üblicherweise Sockets (AF_UNIX, AF_INET, AF_INET6) zum Einsatz.

Sie wird nur i.d.R. über einen Unix-Socket aufgebaut. Theoretisch gibt es noch andere Möglichkeiten der IPC wie z.B. TCP-Socket, Named-Pipes oder Mutexs .
Ein Mutex hat mit IPC nicht direkt zu tun, sondern ist ein Mechanismus zum Schutz einer Ressource vor konkurrierenden Zugriffen; doch das nur am Rande. Völlig egal, ob Du einen Socket (welchen Typs auch immer), eine Pipe oder eine named Pipe verwendest - es handelt sich dabei immer um Dateideskriptoren, und in jedem Fall ist es einem Client-Prozess möglich, sich selbst zu beenden (oder beendet zu werden), ohne dabei den Server zu schießen.

Man muss sich bei FastCGI nur klar machen, dass der FastCGI-Prozess den Server spielt, und der Webserver den Client. Wird der FastCGI-Prozess unabhängig vom Webserver erzeugt (z. B. mit spawn-fcgi), ist selbiger völlig unbeeindruckt davon, wenn der Webserver-Prozess gekillt wird. Nur die besondere Konstellation, dass ein Webserver einen FastCGI-Prozess als Kindprozess selbst erzeugt, bringt eine etwas verzwickte Logik mit sich, da der FastCGI-Prozess die Dateideskriptoren von seinem Elternprozess, dem Webserver, erbt.

Außerdem sehen unixoide Systeme vor, dass ein Kindprozess beim beenden seinen Elternprozess darüber informiert, dass er sich beendet (und ggf. mit welchem Status). Gibt es keinen Elternprozess mehr, oder nimmt der Elternprozess keine Status-Information vom Kindprozess entgegen, entsteht aus dem Kindprozess ein Zombie - ein bereits abgearbeiteter Prozess, der sich nicht ganz beenden kann, weil er seinen Rückgabestatus nicht loswird.

Das nur zur Veranschaulichung, warum die Konstellation "Webserver erzeugt FastCGI-Prozess" so komplex ist. Das FastCGI-Modul muss sicherstellen, dass
  • die Dateideskriptoren, die zur IPC benutzt werden, von beiden Prozessen sauber geschlossen werden (sonst bleiben sie in der Kernel-Tabelle als offene Deskriptoren drin und belasten das System)
  • ein erzeugter FastCGI-Prozess sauber terminieren kann, d. h. sein Elternprozess noch aktiv ist und auch den Rückgabestatus entgegennimmt - ansonsten entstehen Zombies und müllen die Prozesstabelle voll.

Apache-Clients werden vom Parent-Prozess lediglich über ein TERM-Signal (also ein "Bitte beende Dich bei Zeiten") aufgefordert sich zu beenden.
Welches der Child aber nicht tut, weil er sich sagt: "Momentchen, ich habe da noch einen offenen IPC."
Dafür hat der Child einen Signal Handler, der
  1. ein Flag setzt, dass dafür sorgt, dass dieser Childprozess keine neuen Requests mehr zur Bearbeitung aus der Queue holt
  2. dafür sorgt, dass auf die noch in Abarbeitung befindlichen Requests (bei Worker = Threads) gewartet wird
  3. am Ende sicherstellt, dass alle offenen Dateideskriptoren geschlossen werden und einen Rückgabestatus setzt
Das bedeutet natürlich, dass der Child-Prozess noch eine Weile aktiv ist, nachdem er das TERM-Signal gefangen hat.

Es wäre in den meisten Installationen sinnvoll, wenn mod_fcgid das TERM per IPC auch an den fcgid durch reichen würde. Auf der anderen Seite macht es auch Sinn dies nicht zu tun, da fcgid theoretisch ein eigener Server ist und nicht nur von einem Apache-Child abhängig sein muss.
FastCGI-Prozesse werden nicht von den Child-Prozessen erzeugt, sondern von einem gesonderten Management-Prozess. Das FastCGI-Modul sollte dabei selbst erzeugten FastCGI-Prozessen ein TERM-Signal schicken, muss damit aber so lange warten, bis alle Apache-Children beendet wurden - die arbeiten bei einem TERM den aktiven Request ja noch zu Ende ab und müssen dabei ggf. von einem Socket lesen, der sie mit dem FastCGI-Prozess verbindet. Die o. g. Punkte müssen dabei natürlich beachtet werden.
 
Am Rande: Ich lese fleissig mit, ist ab schon etwas komplexere Materie :)

Darf ich fragen, wie Du diesen rein global zu setzenden Parameter auf nur eine Seite beschränkt hast?

Auf meinem Testsystem ist das doch egal, ob der Parameter für alle vHosts greift?!

Ich sehe in dem Logfile-Ausschnitt lediglich die fcgid-Prozesse sterben.

Irgendwie wird mir ist nicht ganz klar, was Du überhaupt wissen willst und was das Experiment bewirken sollte. Deine abschließende Frage bringt ebenfalls keine Erleuchtung.

Ich möchte es einfach nur verstehen.

Die grundsätzliche Arbeitsweise des Apachen bei der Abarbeitung "normaler" Request ist mir nun einigermassen klar und deswegen geht es nun mit dem fcgid-Backend weiter.

Ein bisschen schiele ich auch in Richtung dieses Threads:

Das mit der MaxRequestsPerChild-Direktive habe ich noch einmal ausprobiert: Via `watch -n 1 pstree -p`sieht man gut, dass sich die statischen Worker beenden und neu erzeugt werden (habe MaxRequestsPerChild 1 gesetzt und eine Seite ohne alles aufgerufen - 1 Request also). Beim erneuten Aufruf gibt es neue Worker mit neuen PIDs.

Der httpd-Thread mit IPC zum fcgid-Backend bleibt jedoch am Leben, wenn ich eine PHP-Seite aufrufe, auch nach mehrfachen Requests.

Die fcgi-Instanzen kann man gut mit FcgidMaxRequestsPerProcess isoliert kontrollieren - wenn die Anzahl erreicht ist, beenden sich diese und werden neu erzeugt. Dabei verbinden sie sich aber zum selben Apache-Elternprozess, dessen PID bleibt gleich:

Code:
[debug] worker.c(1363): taking over scoreboard slot from 21388 (quiescing)


Der fcgid-erzeugende httpd-Prozess scheint tatsächlich etwas anderen Mechanismen zu unterliegen, als die Worker für die statischen Anfragen. Es bleibt also immer noch die Frage, wann sich dieser besondere Prozess beendet bzw. wie man das auf httpd.conf-Seite steuern kann...
 
Back
Top