Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]5863[/thread]

prozess beenden und frage zu fork: prozess <defunct> obwohl beendet

Leser: 2


<< >> 10 Einträge, 1 Seite
kmonster
 2003-10-30 03:12
#68134 #68134
User since
2003-08-20
33 Artikel
BenutzerIn
[default_avatar]
ein permanent laufendes script aktualisiert eine datenbank anhand verschiedener parameter mit informationen aus dem netz. da es bei den netzabfragen zum teil zu verzögerungen kommen kann und das script davon nicht beeinflusst werden soll, verzweige ich mittels fork. im kindprozess werden daten aus dem netz abgefragt, in die datenbank eingetragen und danach wird der kinprozess mittels exit beendet. unmittelbar wor dem exit nehme ich noch einen eintrag in eine log datei vor. dieser ist auch immer vorhanden. die kindprozesse stehen danach aber noch längere zeit (paar minuten bis 1 stunde in der prozessliste mit der angabe "[script.pl <defunct>]". warum? werden die prozesse aus irgendwelchen gründen am leben gehalten? im script gibt es keine variablen deren existens vom kindprozess abhängig ist oder ähnliches.

beim verzweigen mit fork bleibt die aktuelle pid manchmal erhalten, manchmal bekommt sie der kindprozess. kann ich dies beeinflussen? es wäre für mich sinnvoll wenn immer der kindprozess die neue pid bekommt.

gruss km
snarf
 2003-10-30 09:23
#68135 #68135
User since
2003-08-14
77 Artikel
BenutzerIn
[default_avatar]
... hmmm, so aus dem Stehgreif kann man dazu wohl kaum was sagen, nur ein paar Fragen hätte ich:

1. Wie verhält sich der Parent-Prozess gegenüber den Children (Stichwort: "reaping children")

2. Die aktuelle PID (vom Parent) kann niemals auf das Child übergehen - absolut unmöglich, denn während das Child "gezeugt" wird, ist der Parent ja noch aktiv und seine PID somit belegt.

Zeig mal den Code, d.h. zumindest die Stelle, an der du forkst.
kmonster
 2003-10-30 11:24
#68136 #68136
User since
2003-08-20
33 Artikel
BenutzerIn
[default_avatar]
ok ich hatte da einen denkfehler. habe den elternprozess beendet und den kindprozess weiterlaufen lassen. der elternprozess wurde dann bis zum nächsten fork als <defunct> angezeigt. habe es jetzt korrigiert, problem jetzt wird jeder erzeugte kindprozess mit <defunct> angezeigt und verschwindet nie. ich möchte aber auch nicht zwischen den prozessen kommunizieren oder warten, sie sollen unabhängig voneinander weiterlaufen.

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
while(sleep 60) {
  for (datenbankabfrage()) {
    my $kind = fork;
    unless ($kind) {
      tu_was($_);
    }
  }
}

sub tu_was {
  ...
  exit 0;
}


ist zwar kein schöner stil mit dem exit aus der subrutine, aber darum gehts ja nicht...
Strat
 2003-10-30 12:04
#68137 #68137
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
du erzeugst jede menge zombies (=~ prozesse, deren vaterprozess tot ist, und die darauf warten, eine beenden-bestaetigung von ihm zu erhalten, die nie kommt, und deshalb die prozesstabelle zumuellen)
Versuche mal, die childprozesse zu entsorgen, indem du im Vaterprozess vor dem fork sowas schreibst wie:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use POSIX qw(:signal_h :errno_h :sys_wait_h);
$SIG{CHLD} = \&Reaper; # diese zeile muss vor dem fork kommen

sub Reaper {
my $pid;
$pid = waidpid(-1, &WNOHANG);
if ($pid == -1) {
# no child waiting => ignore it
}
elsif (WIFEXITED($?)) {
print "Process $pid exited\n";
}
else {
print "False alarm on $pid\n";
}
%SIG{CHLD} = \&Reaper;
} # Reaper
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
snarf
 2003-10-30 12:12
#68138 #68138
User since
2003-08-14
77 Artikel
BenutzerIn
[default_avatar]
... genau dieses exit ist Dein Problem (bzw. die Ursache). Die Children senden eigentlich nach beendigung ein Signal an den Parent. Dieses Signal kommt nirgendwo an ... und die Children werden zu Zombies (defunct process)

Bau folgendes in Deinen Parent ein (Minimal-Variante, aber reicht zumeist aus):

Code: (dl )
$SIG{CHLD} = sub {wait(); exit }


... und dann lass Deinen Parent in einer Endlosschleife auf das Signal warten.

Anders wirst Du dieses Problem wohl nicht in den Griff bekommen.

ReadU, snarf

PS: das exit natürlich nur, wenn Du nicht mehrere Children erzeugst.\n\n

<!--EDIT|snarf|1067508871-->
snarf
 2003-10-30 12:21
#68139 #68139
User since
2003-08-14
77 Artikel
BenutzerIn
[default_avatar]
@kmonster:

by the way: warum forkst du eigentlich? Ein einfacher Background-Aufruf des "ausgelagerten Teils" (ehemals Child code) sollte doch eigentlich reichen, oder?

(Ob das nun auch hilft, die defuncts zu vermeiden ... bin ich gerade überfragt)

snarf
kmonster
 2003-10-30 12:34
#68140 #68140
User since
2003-08-20
33 Artikel
BenutzerIn
[default_avatar]
Quote
prozesse, deren vaterprozess tot ist


hm, der vaterprozess läuft doch immer weiter und ich erzeuge neue kindprozesse, oder verstehe ich da was falsch?

OK es klappt!
habe auch kurz getestet, das warten auf den exit des kindprozesses beeinflusst den vaterprozess nicht, läuft also paralell. genauso brauche is es.

danke!
kmonster
 2003-10-30 12:39
#68141 #68141
User since
2003-08-20
33 Artikel
BenutzerIn
[default_avatar]
@snarf:

habe auch schon drüber nachgedacht einen externen auftruf zu machen, aber fork ist einfach praktischer, da alle variablen bereist da sind...

Quote
PS: das exit natürlich nur, wenn Du nicht mehrere Children erzeugst.


doch das mache ich. wie man vielleicht aus meinem codesnipsel entnehmen kann erzeuige ich evtl eine ganze reihe childs hintereinander.

weiss nicht wie weit sich deine kurzlösung von der von strat unterscheidet, strats klappt soweit, werde jetzt mit mehreren childs testen.
kmonster
 2003-10-30 13:51
#68142 #68142
User since
2003-08-20
33 Artikel
BenutzerIn
[default_avatar]
mit mehreren kindern gab es probleme. habe mir jetzt aus euren ideen folgendes gebastelt. kinder werden erfolgreich beendet und hauptprozess läuft ohne warten weiter:

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
while(sleep 60) {
  for (datenbankabfrage()) {
    my $kind = fork;
    unless ($kind) {
      tu_was($_);
    }
  }
 my $pid = waitpid(-1, &WNOHANG);
}

sub tu_was {
 ...
 exit 0;
}


funktioniert! danke!
Strat
 2003-10-30 16:13
#68143 #68143
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
Meine Loesung installiert einen Signalhandler ($SIG{CHLD} = \&Reaper; ), der aktiviert wird, wenn vom Child ein Bin-Fertig-Signal kommt. Dann wird die Funktion Reaper ausgefuehrt. Dann wird ueberprueft, von woher das Signal kam, ob von einem child, oder system, backticks, STOP oder so.
Nachdem dies ueberprueft wurde, wird der Signalhandler wieder installiert...
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
<< >> 10 Einträge, 1 Seite



View all threads created 2003-10-30 03:12.