Linux, accept() file handle

(Firma: JDCC) #7030308
Lesenswert?

Servus,

Problem: ich baue mir gerade einen einfachen Webserver, er funktioniert
soweit. Ich hab da einen merkwürdigen Effekt:

Schleife {
  fd = accept( ...);
  tu was damit
  sende HTTP 200
}

Beim ersten Aufruf erhalte ich als fd ein 5 oder 6, bei einer
bestimmten Suchfunktion kommt aber nach den 2ten Aufruf als
fd eine 0 zurück und es feuert 7 Anfragen hintereinander.
Also eine Macke in meiner Suchfunktion. Nur welche ?

fd 0 ist eigentlich stdin, Linux übernimmt bei der Generierung
eines fd immer die kleinste freie Zahl, das würde darauf hindeuten
daß ich irgendwo stdin geschlossen habe (habe ich nicht).

Hilfreich wäre irgendeine Funktion die mir aus dem Programm
heraus die belegten Handles mit Dateinamen ausgäbe. Die
Suchfunktion besteht aus > 2200 Zeilen, das ist sonst sehr
mühselig ;)
Gast #7030364
Lesenswert?

Im proc-Filesystem kannst du die offenen Filehandles sehen 
"/proc/<pid>/fd" insb auch "/proc/self/fd".

Ansonsten das Programm einfach mal unter strace starten, insb "strace -e 
trace=desc <program>".

Generell: wenn accept 0 zurück liefer, muss fd 0 vorher geschlossen 
worden sein.
Gast #7030385
Lesenswert?

Joachim D. schrieb:
> Kann ich irgendwie über den fd herausfinden ob dahinter etwas
> steckt ?

Hier mal ein Beispiel für einen Prozess mit Socket und Pipe:
1
# ls -l /proc/1297/fd
2
total 0
3
lrwx------ 1 root root 64 Apr 10 14:38 0 -> /dev/null
4
lrwx------ 1 root root 64 Apr 10 14:38 1 -> /dev/null
5
lrwx------ 1 root root 64 Apr 10 14:38 2 -> /dev/null
6
lrwx------ 1 root root 64 Apr 10 14:38 3 -> socket:[1791]
7
lr-x------ 1 root root 64 Apr 10 14:38 4 -> pipe:[8985]
(Firma: JDCC) #7030393
Lesenswert?

Bei mir:

insgesamt 0insgesamt 0
lrwx------ 1 jd jd 64 Apr 10 14:46 0 -> /dev/pts/1
lrwx------ 1 jd jd 64 Apr 10 14:46 1 -> /dev/pts/1
lrwx------ 1 jd jd 64 Apr 10 14:46 2 -> /dev/pts/1
l-wx------ 1 jd jd 64 Apr 10 14:46 3 -> /home/jd/web/bin/prt/uquery.prt
lrwx------ 1 jd jd 64 Apr 10 14:46 4 -> socket:[121536]

und nach dem Fehler:

insgesamt 0
lrwx------ 1 jd jd 64 Apr 10 14:46 1 -> /dev/pts/1
lrwx------ 1 jd jd 64 Apr 10 14:46 2 -> /dev/pts/1
l-wx------ 1 jd jd 64 Apr 10 14:46 3 -> /home/jd/web/bin/prt/uquery.prt
lrwx------ 1 jd jd 64 Apr 10 14:46 4 -> socket:[121536]

Das eine /dev/pts/1 (was immer das ist) fehlt.
Gast #7030396
Lesenswert?

Programmatisch:
1
static void
2
show_fd0()
3
{
4
    char buf[256];
5
    ssize_t n;
6

7
    n = readlink("/proc/self/fd/0", buf, sizeof(buf)-1);
8
    if (n >= 0)
9
    {
10
        buf[n] = 0;
11
        puts(buf);
12
    }
13
    else
14
        perror("readlink");
15
}
Gast #7030408
Lesenswert?

Ich vermute ja, dass du in deiner Schleife
> Schleife {
>   fd = accept( ...);
>   tu was damit
>   sende HTTP 200
> }

den falschen Filehandle schließt, statt close(fd) also close(0) bzw 
irgendwo fd auf 0 gesetzt wird oder das ursprüngliche fd verdeckt wird 
(shadowed var) oder so was.
#7030414
Lesenswert?

Joachim D. schrieb:
> Das eine /dev/pts/1 (was immer das ist) fehlt.

Das ist ein Pseudoterminal.
Aber es sollte doch nicht so schwer zu finden sein, wo du fd 0 schließt. 
Meine Vermutung: Du übergibst irgendwo eine Variable an close(), von der 
du denkst, dass sie irgendeinen fd enthält, den du dir gemerkt hast, 
aber in Wirklichkeit hat sie noch ihren vorinitialisierten Wert von 0. 
Deshalb initialisiere ich alle Variablen, die fds enthalten sollen, mit 
-1.
(Firma: JDCC) #7030424
Lesenswert?

foobar schrieb:
> den falschen Filehandle schließt, statt close(fd) also close(0) bzw
> irgendwo fd auf 0 gesetzt wird oder das ursprüngliche fd verdeckt wird
> (shadowed var) oder so was.

Irgendwo ... Die fragliche Suchfunktion ist seit ca 15 Jahren
organisch gewachsen und arbeite als CGI-Programm (das Programm
wird auch immer beenden, da fallen solche Macken nicht auf).

Ich portiere das alles gerade nach Linux und lassen das im
Rahmen eines kleinen Webservers laufen (wird also nicht komplett
beendet).

Ich habe mir gerade mal ein kleines Prüfprogrännchen eingebaut
das mit readlink() die fd's anzeigt. Es schießt mir die 0.

Rolf M. schrieb:
> Deshalb initialisiere ich alle Variablen, die fds enthalten sollen, mit
> -1.

Mache ich mittlerweile auch ...

Zumindest ist mir jetzt klarer nach was ich suchen muß ;)

Vielen Dank !

(bin noch ziemlich neu in Linux)
Gast #7030430
Lesenswert?

Evtl. hast Du irgendwo einen Buffer Overflow fabriziert und 
überschreibst dabei einen auf dem Stack liegenden FD-Parameter mit 0.

Kann z.B. bei einem memset() oder bzero() passieren, wenn man nicht 
sizeof benutzt.
Gast #7030454
Lesenswert?

Zum debuggen kann man auch mal etwas pfuschen:
1
#define close(fd) ((fd)==0 ? abort(),-1 : (close)(fd))

generiert dir dann, zumindest in den mit diesem define übersetzten 
Teilen, einen Core-dump den du dir mit dem gdb anschauen kannst.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren