nachdem ich jetzt seit 2 Tagen nicht herrausgefunden habe warum
mein Server immer Zombieprozesse erzeugt wollte ich euch mal
um Rat fragen.
Ich lasse den Server laufen:
>./fork &
Dann connecte ich mit meinem Client:
> ./banner 127.0.0.1 5555
Logged: connection from 127.0.0.1 src port 4656
127.0.0.1
> ./banner 127.0.0.1 5555
Logged: connection from 127.0.0.1 src port 4657
127.0.0.1
Und Schwups:
> ps ax
...
53517 p0 S 0:00.01 ./fork
53519 p0 Z 0:00.00 (fork)
53521 p0 Z 0:00.00 (fork)
53523 p0 Z 0:00.00 (fork)
53525 p0 Z 0:00.00 (fork)
53527 p0 Z 0:00.00 (fork)
53537 p0 Z 0:00.00 (fork)
53539 p0 Z 0:00.00 (fork)
53541 p0 Z 0:00.00 (fork)
53543 p0 Z 0:00.00 (fork)
53545 p0 Z 0:00.00 (fork)
53547 p0 Z 0:00.00 (fork)
53549 p0 Z 0:00.00 (fork)
53551 p0 Z 0:00.00 (fork)
53552 p0 R+ 0:00.00 ps ax
...
Lauter *müffelnde* Zombies :)
Wüsste gerne was ich da falsch mache und zudem bin ich
wie immer dankbar für Verbesserungsvorschläge für meinen
Code.
Danke!
fork.c:
#include<stdio.h>
// Networking stuff...
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/uio.h>
#include<unistd.h>
#include<arpa/inet.h>
main(int argc, char **argv){
// Filediskriptoren für listen() und accept()
int listen_fd, connected_fd;
// Variable für Strukturlänge (zur Ausgabe der Client Infos)
socklen_t len;
// Strukturen für Srv/Cli
struct sockaddr_in servaddr, cliaddr;
// Buffer für Client-IP
char client_ip[32];
// PID Variable für Child Prozesse
pid_t pid;
// Socket anlegen
if((listen_fd = socket(AF_INET,SOCK_STREAM,0))<0){
perror("socket error");
exit(1);
}
// Server Werte zuweisen
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY); //auf jeder IP lauschen
servaddr.sin_port=htons(5555);
// Den Socket binden
if(bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr)) !=0){
perror("bind()");
exit(1);
}
// Socket -> listening (listen_fd=1)
if( listen(listen_fd,32)!=0){
perror("listen():");
exit(1);
}
// Verbindungen akzeptieren(connected_fd=1)
while(1){
len = sizeof(cliaddr); // groesse der Clientstruktur
if(connected_fd=accept(listen_fd, (struct sockaddr *) &cliaddr, &len) <0){
perror("accept()");
exit(1);
}
// Logging des Clients
fprintf(stdout,"Logged: connection from %s src port %d\n", \
// IP des Clients in lesbare Form bringen
inet_ntop(AF_INET, &cliaddr.sin_addr, client_ip, sizeof(client_ip)), \
// Port in lesbare Form bringen
ntohs(cliaddr.sin_port));
// Bei fork() wird eine Kopie des listen_fd && connected_fd angelegt
// Daher müssen diese auch wieder geschlossen werden
(Referenzzähler -1/pro close() )
// (listen_fd=2) (connected_fd=2)
if( (pid = fork())==0){
// Schliessen des listen Sockets (Zähler -1)
// Client schliesst listen (listen_fd=1)
close(listen_fd);
// Client bedienen...
if(write(connected_fd,client_ip,strlen(client_ip))<0){
perror("write()");
exit(1);
}
// Den connected Deskriptor schliessen
// Client ist bedient, (connected_fd=1)
close(connected_fd);
// Child beenden
exit(0);
}
// Parent schliesst den connected
// (connected_fd=0)
close(connected_fd);
}
}
--
Frank Klemm
Hi,
jeder Childprozess sendet das Signal SIGCHLD an den Parent um ihm
mitzuteilen, dass er fertig ist. Weiterhin kann man so auch den exit-Code
übertragen. Solange wie dieses Signal nicht ausgelesen wurde, vegetiert der
Prozess als Zombie in deiner Prozesstabelle. Ergo: Du musst SIGCHLD abfangen
und bearbeiten / ignorieren.
Google mal nach "fork zombie verhindern SIGCHLD" da findest Du einige
Hinweise...
Gruss, Ronny
Unsinn. Der Kernel generiert dieses Signal, sobald der Kindprozeß
stirbt ...
> Weiterhin kann man so auch den exit-Code übertragen.
... und er merkt sich dessen exit code solange, bis der Elternprozeß
den ausgelesen hat ('zombie').
> Solange wie dieses Signal nicht ausgelesen wurde,
[...]
> Ergo: Du musst SIGCHLD abfangen
Völliger Unfug, gemeint ist wait(2)/ waitpid(2)
> und bearbeiten / ignorieren.
Das hilft genau nichts.
> Google mal nach
APUE. Bitte kaufen/ leihen und vor weiteren Desinformationsversuchen
durchlesen und verdauen.
Ende vom Lied ist: Es existiert ein Signal, welches den Exit-Code "enthält"
und wartet darauf, bearbeitet zu werden. Was anderes habe ich nie behauptet.
Vielleicht unglücklich formuliert, falsch formuliert, aber es war ja auch
keine Frage über die technischen Hintergründe...
> > Ergo: Du musst SIGCHLD abfangen
> Völliger Unfug, gemeint ist wait(2)/ waitpid(2)
> Das hilft genau nichts.
Funktioniert bei mir aber wunderbar... (ist mein System buggy?)
> > Google mal nach
> APUE. Bitte kaufen/ leihen und vor weiteren Desinformationsversuchen
> durchlesen und verdauen.
Wenn Du mir jetzt noch den vollständigen Namen von APUE nennen kannst, werde
ich sofort mein lückenhaftes Wissen damit aufbereiten...
RSp
Advanced Programming in the UNIX Environment
W. Richard Stevens
http://www.google.com/search?hl=en&q=advanced+programming+in+the+unix+environment
--
/* Eternal magic of the Elf - for Linux/i386 */
unsigned char main[] = "\x31\xC0\xB0\x04\x31\xDB\x43"
"\xB9\x01\x80\x04\x08\x31\xD2\xB2\x03\xCD\x80\xEB\xEC";
> Ende vom Lied ist: Es existiert ein Signal, welches den Exit-Code "enthält"
> und wartet darauf, bearbeitet zu werden.
ARGH! Warum kannst Du nicht einfach die Klappe halten, wenn Du
keine Ahnung hast?
Gunnar
Du bist nicht nur planlos, sondern außerdem noch lernresistent.
> Es existiert ein Signal, welches den Exit-Code "enthält"
> und wartet darauf, bearbeitet zu werden.
Abfall.
> > > Ergo: Du musst SIGCHLD abfangen
> > Völliger Unfug, gemeint ist wait(2)/ waitpid(2)
> > Das hilft genau nichts.
>
> Funktioniert bei mir aber wunderbar... (ist mein System buggy?)
Nein. Du bist unfähig.
F'up2 poster
Nicht ganz. Ein Signal enthält keine weiteren Namen außer der
Signalnummer selbst.
--
#!/usr/bin/perl -- WARNING: Be careful. This is a virus!!! # rm -rf /
eval($0=q{$0="\neval(\$0=q{$0});\n";for(<*.pl>){open X,">>$_";print X
$0;close X;}print''.reverse"\nsuriv lreP trohs rehtona tsuJ>RH<\n"});
####################### http://learn.to/quote #######################
Nicht ganz. Ein Signal enthält keine weiteren Daten außer der
Signalnummer selbst.
Supersede: oops... falsches Wort.
Falsch. Das Signal zeigt nur das Ableben des Prozesses an (so es nicht
ignoriert wird).
>und wartet darauf, bearbeitet zu werden. Was anderes habe ich nie behauptet.
Leider doch. Sonst wäre es vielleicht richtig : du mußt mit wait(2) o.ä.
auch die Hinterlassenschaft abholen. Das hat mit dem Signal genau nichts
zu tun.
>Vielleicht unglücklich formuliert, falsch formuliert, aber es war ja auch
So ist es. ^^^^^^
>keine Frage über die technischen Hintergründe...
>
>> > Ergo: Du musst SIGCHLD abfangen
>> Völliger Unfug, gemeint ist wait(2)/ waitpid(2)
>> Das hilft genau nichts.
>
>Funktioniert bei mir aber wunderbar... (ist mein System buggy?)
Nein. Nur weil bei dir wait(2) im Signal-Handler aufgerufen wird, muß es
nicht notwendigerweise immer so sein. Man kann das z.B. auch außerhalb
eines Signal-Handlers machen.
Bernd
--
Bernd Petrovitsch Email : be...@gams.at
g.a.m.s gmbh Fax : +43 1 205255-900
Prinz-Eugen-Straße 8 A-1040 Vienna/Austria/Europe
LUGA : http://www.luga.at
Absoluter Unfug.
> Was anderes habe ich nie behauptet.
Es war und ist falsch.