linux-l: portmap, glibc, svc_getreqset, viele FDs und SIGSEGV (episch)

Oliver Hillmann oh at novaville.de
Mo Mär 6 17:34:08 CET 2000


Hallo,

mein portmap segfaultet.

VORGESCHICHTE:

Ich habe einen Kernel 2.2.13, der von mir entsprechend gepatched und
neukompiliert wurde, sodaß er die Begrenzung von offenen
Filedeskriptoren pro Prozeß von 1024 auf 2200 erhöht. (Dazu sind
entsprechend die Defaultwerte für NR_OPEN in den Dateien
/usr/src/linux/include/linux/{fs.h,limits.h} zu ändern. Vgl.
/usr/src/linux/Documentation/proc.txt, Zeilen 462ff, oder auch FAQ
der GLIBC, Punkt 2.25)

Die Einträge sind nun:

fs.h:
/* #define NR_OPEN (1024*1024) */   /* Absolute upper limit on fd
num */
#define NR_OPEN (2200*1024)
#define INR_OPEN 2200      /* Initial setting for nfile rlimits */

und
limits.h:
#define NR_OPEN      2200

Funktioniert ganz prima, die Gesamtzahl aller Filedeskriptoren ist
natürlich weiterhin in /proc/sys/fs/file-max zu setzen.

DAS PHÄNOMEN

Wenn ich nun allerdings portmap (Version 4.0.15, neukompiliert aus
der portmap-4.0.15.src.rpm oder als Binary rpm installiert; Version
5beta, ebenfalls als Binary oder aus dem SuSE Source RPM gebaut)
starte, und ein erster rpcinfo Request trifft auf portmap, dann
gibts einen Segmentation Fault.

strace zeigt mir, daß der letzte syscall vor dem SIGSEGV ein accept
war. gdb informiert mich über den Crash in svc.c:429 in der Funktion
svc_getreqset. Das ist nun aber nichts, was portmap mitbringt,
sondern eine Funktion der Glibc. Im Unterverzeichnis sunrpc der
glibc-Sourcen befindlich, hat das wohl unmittelbar was mit RPC, und
damit mit dem Portmapper zu tun.

Was es mit den svc_*-Funktionen auf sich hat, weiß ich nicht, ich
hab in der glibc Doku nichts gefunden (steht unter gnu.org unter
missing-docs.html, ist also undokumentiert.) Andere Doku besagt, daß
sei eine Funktion, die Requests auf Sockets bedient, wenn svc_run()
nicht genutzt wird.

Details:

gdb sagt:

Program received signal SIGSEGV, Segmentation fault.
svc_getreqset (readfds=0xbffff858) at svc.c:429
svc.c:429: No such file or directory.
(gdb) p readfds
$1 = (fd_set *) 0xbffff858
(gdb) p *readfds
$2 = {fds_bits = {64, 0 <repeats 31 times>}}


strace sagt:

myhost:~ # strace portmap -d [Haufen Zeugs] setuid(1)  = 0
sigaction(SIGINT, {0x804a690, [], SA_NOMASK|0x4bd6}, {SIG_DFL}) = 0
sigaction(SIGCHLD, {SIG_IGN}, {SIG_DFL}) = 0 select(2200, [3 4 1026
1027 1029 1032 1033 1036 1037 1038 1039 1040 1041 1042 1043 1044
1045 1046 1047 1048 1049 1050 1051 1052 1053 ...
   [Es folgen alle Zahlen (Filedeskriptoren 1055-2163! So sieht
    select() nicht gut aus!!!!]
2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2175], NULL, NULL,
NULL) = 1 (in [4 1026 1027 1029 1032 1033 1036 1037 1038 1039 1040..
   [Nochmal Zahlen (Deskriptoren?!), nun 1055-1604]
1606 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620])

   [rpcinfo -p myhost von irgendwo]

accept(4, {sin_family=AF_INET, sin_port=htons(995), sin_addr=inet_addr("192.168.1.252")}, [16]) = 5
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++
myhost:~ #

Was passiert denn da bei select?! Bei ungepatchten Kernels und
portmap sieht das nämlich so aus:

otherhost:~ # strace portmap -d
select(1024, [3 4], NULL, NULL, NULL)   = 1 (in [4])

    [rpcinfo -p otherhost von irgendwo]

accept(4, {sin_family=AF_INET, sin_port=htons(618),
sin_addr=inet_addr("192.168.1.252")}, [16]) = 5
select(1024, [3 4 5], NULL, NULL, NULL) = 1 (in [5])


MEINE FRAGE:

Was passiert hier? Wo liegt der Fehler? Any ideas? Ich hab da jetzt
an mehreren Tagen einige Stunden vorgesessen und sehe vielleicht den
Wald vor lauter Bäumchen nicht mehr... (Auch das Anpassen von
__FD_SETSIZE in /usr/include/gnu/types.h hat nix genützt...)

Alle Ideen willkommen (und sorry für die fette Mail ;)

Oli

P.S.: So passiert mit GLIBC 2.0.6 und 2.1.1 auf SuSE 6.2 bzw. RedHat
6.0. Portmap wie angegeben, kein knfs (falls das eine Rolle spilet)
P.P.S.: Und: ja, manche Prozesse brauchen tatsächlich so viele
Deskriptoren...
P.P.P.S.: Jaja, das mag schlechtes Design sein....



Mehr Informationen über die Mailingliste linux-l