3 Stimmen

Wie debuggen Sie ein mod_perl2-Modul, ohne es neu zu starten?

Umgebung: Apache/2.2.11 (Win32) mod_apreq2-20051231/2.6.2-dev mod_perl/2.0.4-dev Perl/v5.10.0

Situation sehr ähnlich wie in diesem Diskussionslistenbeitrag beschrieben, außer dass es sich um win32 handelt.

Ich habe dies in der httpd.conf:

PerlModule Apache2::Reload
PerlInitHandler Apache2::Reload
PerlSetVar ReloadAll Aus
PerlSetVar ReloadModules "MeinPaket::*"

... sowie nur mod_perl-Script-Handling.

Ich habe ein Skript, das ein MyPackage-Modul verwendet, und es funktioniert.

Ich unterbreche das Modul und lade das Skript neu. Der Fehler ist ein hilfreicher, der die Zeile angibt, an der ich das Modul unterbrochen habe.

(Wenn ich an diesem Punkt erneut lade, wird mir nur "Undefined subroutine &ModPerl::ROOT::ModPerl::Registry..." angezeigt, weil es beim ersten Mal nicht gelungen ist, die Datei zu laden. Aber so oder so tritt das folgende Verhalten immer noch auf.)

Ich behebe den Fehler und berühre auch die Skriptdatei, damit das Modul neu geladen wird, und lade neu. Jetzt steht dort:

Der Versuch, MyPackage/Foo.pm neu zu laden, wurde abgebrochen.
Die Kompilierung schlug beim Erfordern von E:/dev/test.pl in Zeile 4 fehl.

Selbst wenn ich das Skript und das Modul berühre, kann ich es nicht richtig neu laden, außer durch Neustarten des Webservers.

Das Unterbrechen des Skripts selbst (im Gegensatz zum Modul) funktioniert einwandfrei: richtige Fehler und beim Zurückändern funktioniert es beim Neu laden wieder.

Nach jedem dieser Dinge habe ich den Webserver vor dem Testen neu gestartet:

  1. Ich habe versucht, eine Spur zu verfolgen, aber die Zeile, bei der es weiterhin Fehler gibt, ist ModPerl/RegistryCooker.pm Zeile 204, was nur die Zeile ist, die das gesamte Skript eval{}t.

  2. Ich habe versucht, "use warnings FATAL => 'all'" einfach in "use warnings" im Skript und im Modul zu ändern. Hat keinen Unterschied gemacht.

  3. Ich habe meine benutzerdefinierte $SIG{__DIE__}-Funktion deaktiviert. Hat keinen Unterschied gemacht. (Nun ja, nur wo der Fehler erschien, natürlich, aber die generierten Fehler waren die gleichen.)

  4. Gemäß des Diskussionslinks am Anfang habe ich festgestellt, dass MaxRequestsPerChild die ganze Zeit 0 war, und ich habe ThreadsPerChild 1 ausprobiert, aber keine Unterschiede festgestellt. Ich habe MaxRequestsPerChild auf 1 gesetzt, was die seltsamen Verhaltensweisen dieser Frage löst, den Webserver aber nach jedem einzelnen Request neu startet:

    Child 7072: Prozess verlässt, weil er MaxRequestsPerChild erreicht hat. Signalisierung an den übergeordneten Prozess, einen neuen Kindprozess neu zu starten.
    Übergeordneter Prozess: Erhalten des Neustartsignals -- Neu starten des Servers.

    Dies ist keine gute Lösung, da ein erheblicher Codeabschnitt ausgeführt wird, wenn eine Seite zum ersten Mal aufgerufen wird.

  5. Auch gemäß der Diskussion führe ich httpd als Dienst aus, also habe ich -X im Dienstparameterfenster hinzugefügt und auf Start geklickt, und es hat immer noch versucht, nach vollen drei Minuten zu starten (normalerweise startet es innerhalb von 3 Sekunden). Habe sogar eine Timeout-Meldung erhalten. Prozess über den Task-Manager beendet und überprüft, dass ich die Seite nicht mit einem Webbrowser aufrufen konnte. Habe httpd -X von der Befehlszeile aus gestartet. Immer noch dasselbe Verhalten wie zu Beginn dieser Frage. Mir ist auch aufgefallen, dass -X nicht aufgelistet war, als ich httpd -? ausführte. Vielleicht ist es im Win32 MPM nicht verfügbar?

  6. In diesem Thread merkt David an:

    Meine Erfahrung bei der Fehlersuche in dieser Art von Problem hat gezeigt, dass es wahrscheinlich ist, dass das entladene Modul einen Wert gelöscht hat, der im Paketbereich des neu geladenen Moduls gespeichert war (wahrscheinlich zur Zeit des BEGIN-Blocks), den das anschließende Erfordern nicht wiederhergestellt hat.

    Aber das trifft nicht auf meinen Code zu. Der Fehler, den ich im Skript hinzufüge, besteht lediglich darin, eine zusätzliche 'my $var'-Zeile über eine bereits vorhandene hinzuzufügen, sodass die zweite beschwert sich, dass sie bereits deklariert wurde.

Gibt es keine Möglichkeit, an mod_perl2-Modulen zu arbeiten, ohne dass der Webserver nach jedem Neuladen neu startet (ob automatisch über MaxRequestsPerChild oder manuell wie zuvor)?

2voto

Kev Punkte 15003

Kopieren Sie das Sub in das Skript, von dem aus Sie es aufrufen, und platzieren Sie diesen Code vor dem Kopieren:

Paket MyPackage::Foo;
keine Warnungen 'redefine';

Wenn Sie mit den Änderungen fertig sind, verschieben Sie das Sub zurück zu dem tatsächlichen Modul.

0 Stimmen

Du musst es nach dem Zurückkopieren (manchmal!) neu starten, aber es ist trotzdem hilfreich bis dahin.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X