Bug 61047

Summary: HEAVY memory leak in kio_nfs
Product: [Unmaintained] kio Reporter: Jens <jens-bugs.kde.org>
Component: nfsAssignee: Alexander Neundorf <neundorf>
Status: RESOLVED WORKSFORME    
Severity: normal    
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: unspecified   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description Jens 2003-07-10 15:54:41 UTC
Version:            (using KDE 3.1.9)
Compiler:          gcc version 3.3 (Debian)
OS:          Linux (i686) release 2.2.20

I'm  browsing a NFS server share that nmap tells me comes from a "Solaris 8 early access or final release" machine. Suddenly Konqueror stops, while reading a directory, and the kio_nfs process starts eating all memory. 'strace' on this process shows things like


write(6, "\200\0\0|1\324R\273\0\0\0\0\0\0\0\2\0\1\206\243\0\0\0\2"..., 128) = 128
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "\200\0\32\2401\324R\273\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0"..., 4000) = 1448
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "\0\0O\251\0\0\0\tSUNWcamow\0\0\0\0\0\4(\0\0\0\1\0\0j\31"..., 4000) = 1448
brk(0)                                  = 0xcf6b000
brk(0xcf6c000)                          = 0xcf6c000
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "m\0\0\0\0\0\10<\0\0\0\1\0\6\255I\0\0\0\tSUNWdfb.u\0\0\0"..., 4000) = 1448
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "f\0\0\0\0\0\fd\0\0\0\1\0\0\r\354\0\0\0\tSUNWeusru\0\0\0"..., 4000) = 1448
brk(0)                                  = 0xcf6c000
brk(0xcf6d000)                          = 0xcf6d000
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "SUNWhxplt\0\0\0\0\0\20\264\0\0\0\1\0\1$e\0\0\0\tSUNW"..., 4000) = 1028
brk(0)                                  = 0xcf6d000
brk(0xcf6e000)                          = 0xcf6e000
brk(0)                                  = 0xcf6e000
brk(0xcf6f000)                          = 0xcf6f000
brk(0)                                  = 0xcf6f000
brk(0xcf70000)                          = 0xcf70000
brk(0)                                  = 0xcf70000
brk(0xcf71000)                          = 0xcf71000
write(6, "\200\0\0|0\324R\273\0\0\0\0\0\0\0\2\0\1\206\243\0\0\0\2"..., 128) = 128
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "\200\0\32\2400\324R\273\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0"..., 4000) = 1448
brk(0)                                  = 0xcf71000
brk(0xcf72000)                          = 0xcf72000
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "\0\0O\251\0\0\0\tSUNWcamow\0\0\0\0\0\4(\0\0\0\1\0\0j\31"..., 4000) = 1448
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "m\0\0\0\0\0\10<\0\0\0\1\0\6\255I\0\0\0\tSUNWdfb.u\0\0\0"..., 4000) = 1448
brk(0)                                  = 0xcf72000
brk(0xcf73000)                          = 0xcf73000
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "f\0\0\0\0\0\fd\0\0\0\1\0\0\r\354\0\0\0\tSUNWeusru\0\0\0"..., 4000) = 1448
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "SUNWhxplt\0\0\0\0\0\20\264\0\0\0\1\0\1$e\0\0\0\tSUNW"..., 4000) = 1028
brk(0)                                  = 0xcf73000
brk(0xcf74000)                          = 0xcf74000
brk(0)                                  = 0xcf74000
brk(0xcf75000)                          = 0xcf75000
brk(0)                                  = 0xcf75000
brk(0xcf76000)                          = 0xcf76000
brk(0)                                  = 0xcf76000
brk(0xcf77000)                          = 0xcf77000
brk(0)                                  = 0xcf77000
brk(0xcf78000)                          = 0xcf78000
write(6, "\200\0\0|/\324R\273\0\0\0\0\0\0\0\2\0\1\206\243\0\0\0\2"..., 128) = 128
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "\200\0\32\240/\324R\273\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0"..., 4000) = 4000
brk(0)                                  = 0xcf78000
brk(0xcf79000)                          = 0xcf79000
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "SUNWeudbd\0\0\0\0\0\vh\0\0\0\1\0\2\276\245\0\0\0\tSUNW"..., 4000) = 2820
brk(0)                                  = 0xcf79000
brk(0xcf7a000)                          = 0xcf7a000
brk(0)                                  = 0xcf7a000
brk(0xcf7b000)                          = 0xcf7b000
brk(0)                                  = 0xcf7b000
brk(0xcf7c000)                          = 0xcf7c000
brk(0)                                  = 0xcf7c000
brk(0xcf7d000)                          = 0xcf7d000
brk(0)                                  = 0xcf7d000
brk(0xcf7e000)                          = 0xcf7e000
write(6, "\200\0\0|.\324R\273\0\0\0\0\0\0\0\2\0\1\206\243\0\0\0\2"..., 128) = 128
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "\200\0\32\240.\324R\273\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0"..., 4000) = 4000
brk(0)                                  = 0xcf7e000
brk(0xcf7f000)                          = 0xcf7f000
brk(0)                                  = 0xcf7f000
brk(0xcf80000)                          = 0xcf80000
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "SUNWeudbd\0\0\0\0\0\vh\0\0\0\1\0\2\276\245\0\0\0\tSUNW"..., 4000) = 2820
brk(0)                                  = 0xcf80000
brk(0xcf81000)                          = 0xcf81000
brk(0)                                  = 0xcf81000
brk(0xcf82000)                          = 0xcf82000
brk(0)                                  = 0xcf82000
brk(0xcf83000)                          = 0xcf83000
brk(0)                                  = 0xcf83000
brk(0xcf84000)                          = 0xcf84000
brk(0)                                  = 0xcf84000
brk(0xcf85000)                          = 0xcf85000
write(6, "\200\0\0|-\324R\273\0\0\0\0\0\0\0\2\0\1\206\243\0\0\0\2"..., 128) = 128
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "\200\0\32\240-\324R\273\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0"..., 4000) = 1448
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "\0\0O\251\0\0\0\tSUNWcamow\0\0\0\0\0\4(\0\0\0\1\0\0j\31"..., 4000) = 1448
brk(0)                                  = 0xcf85000
brk(0xcf86000)                          = 0xcf86000
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "m\0\0\0\0\0\10<\0\0\0\1\0\6\255I\0\0\0\tSUNWdfb.u\0\0\0"..., 4000) = 2896
brk(0)                                  = 0xcf86000
brk(0xcf87000)                          = 0xcf87000
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "SUNWhxplt\0\0\0\0\0\20\264\0\0\0\1\0\1$e\0\0\0\tSUNW"..., 4000) = 1028
brk(0)                                  = 0xcf87000
brk(0xcf88000)                          = 0xcf88000
brk(0)                                  = 0xcf88000
brk(0xcf89000)                          = 0xcf89000
brk(0)                                  = 0xcf89000
brk(0xcf8a000)                          = 0xcf8a000
brk(0)                                  = 0xcf8a000
brk(0xcf8b000)                          = 0xcf8b000
write(6, "\200\0\0|,\324R\273\0\0\0\0\0\0\0\2\0\1\206\243\0\0\0\2"..., 128) = 128
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "\200\0\32\240,\324R\273\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0"..., 4000) = 1448
brk(0)                                  = 0xcf8b000
brk(0xcf8c000)                          = 0xcf8c000
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "\0\0O\251\0\0\0\tSUNWcamow\0\0\0\0\0\4(\0\0\0\1\0\0j\31"..., 4000) = 2896
brk(0)                                  = 0xcf8c000
brk(0xcf8d000)                          = 0xcf8d000
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "f\0\0\0\0\0\fd\0\0\0\1\0\0\r\354\0\0\0\tSUNWeusru\0\0\0"..., 4000) = 1448
poll([{fd=6, events=POLLIN, revents=POLLIN}], 1, 20000) = 1
read(6, "SUNWhxplt\0\0\0\0\0\20\264\0\0\0\1\0\1$e\0\0\0\tSUNW"..., 4000) = 1028
brk(0)                                  = 0xcf8d000
brk(0xcf8e000)                          = 0xcf8e000
brk(0)                                  = 0xcf8e000
brk(0xcf8f000)                          = 0xcf8f000
brk(0)                                  = 0xcf8f000
brk(0xcf90000)                          = 0xcf90000
brk(0)                                  = 0xcf90000
brk(0xcf91000)                          = 0xcf91000
brk(0)                                  = 0xcf91000
brk(0xcf92000)                          = 0xcf92000


etc etc yadda yadda. I would use valgrind if somebody told me how to attach it to a running kio_nfs process (or else, how to watch kio_nfs if it is started by kdeinit and you don't want valgrind to monitor your whole X session).


Thanks! :)

-- Jens
Comment 1 George Staikos 2003-09-22 20:04:31 UTC
You can't attach valgrind to a running process.  try gdb and see if you can find out 
where it's misbehaving.  Otherwise you have to run the slave in valgrind from the 
start - much more difficult/annoying.  I recommend the gdb approach. 
Comment 2 Jens 2004-02-07 19:12:16 UTC
cannot reproduce any more with 3.2.0-final. closing my bug.
Comment 3 Peter Faasse 2008-07-11 01:17:24 UTC
I observe what i -as far as i can see- is described here in kde-3.5.9 . Both the nfs server and the client machine are linux machines. I use zeroconf:/ as url & avahi (0.6.23) to initiate the nfs:/ 

kernel: 2.6.24.4
gcc: 4.2.3

During the 'memory-eating' activity there is not network activity that i can observe. 

When all memory is exhausted, konqueror pops up with the messagebox:

the process for the nfs://dr108.local protocol died unexpectedly.

After that, the machine resumes work as normal. 

I had an strace running in another konsole, the output of that looks very much like what is described here.

I'll see if i can build a non-stripped kdebase, and see if i can find out what is going on here. Localtime here is 01:17 now, so it's a bit late to do that now ;-)
Comment 4 Peter Faasse 2008-07-12 12:41:12 UTC
Ok, rebuild of kdebase is done; i'm now running a non-stripped kde base. 
The problem as mentioned before is still present & the same. 
Not each & every nfs-export directory does trigger the behaviour, but those that do, do so very reproducible. I can 'attach' a gdb to a kio_nfs pid, and trace the behaviour. So far, i've got the follwing: (now going to see if that makes any sense ;-)
---------------8<-----------------
849         if ( d->deref() ) {
(gdb)
570           for (entry *dirEntry=listres.readdirres_u.reply.entries;dirEntry!=0;dirEntry=dirEntry->nextentry)
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
849         if ( d->deref() ) {
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
850             if ( d != shared_null )
(gdb)
851                 d->deleteSelf();
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
850             if ( d != shared_null )
(gdb)
851                 d->deleteSelf();
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
573                 filesToList.append(dirEntry->name);
(gdb)
565         void detach() { if ( sh->count > 1 ) detachInternal(); }
(gdb)
107         QValueListIterator( NodePtr p ) : node( p ) {}
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
107         QValueListIterator( NodePtr p ) : node( p ) {}
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
570           for (entry *dirEntry=listres.readdirres_u.reply.entries;dirEntry!=0;dirEntry=dirEntry->nextentry)
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
849         if ( d->deref() ) {
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
850             if ( d != shared_null )
(gdb)
851                 d->deleteSelf();
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
850             if ( d != shared_null )
(gdb)
851                 d->deleteSelf();
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
573                 filesToList.append(dirEntry->name);
(gdb)
565         void detach() { if ( sh->count > 1 ) detachInternal(); }
(gdb)
107         QValueListIterator( NodePtr p ) : node( p ) {}
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
107         QValueListIterator( NodePtr p ) : node( p ) {}
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
570           for (entry *dirEntry=listres.readdirres_u.reply.entries;dirEntry!=0;dirEntry=dirEntry->nextentry)
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
849         if ( d->deref() ) {
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
850             if ( d != shared_null )
(gdb)
851                 d->deleteSelf();
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
850             if ( d != shared_null )
(gdb)
851                 d->deleteSelf();
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
573                 filesToList.append(dirEntry->name);
(gdb)
565         void detach() { if ( sh->count > 1 ) detachInternal(); }
(gdb)
107         QValueListIterator( NodePtr p ) : node( p ) {}
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
107         QValueListIterator( NodePtr p ) : node( p ) {}
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
570           for (entry *dirEntry=listres.readdirres_u.reply.entries;dirEntry!=0;dirEntry=dirEntry->nextentry)
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
849         if ( d->deref() ) {
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
850             if ( d != shared_null )
(gdb)
851                 d->deleteSelf();
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
850             if ( d != shared_null )
(gdb)
851                 d->deleteSelf();
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
573                 filesToList.append(dirEntry->name);
(gdb)
565         void detach() { if ( sh->count > 1 ) detachInternal(); }
(gdb)
107         QValueListIterator( NodePtr p ) : node( p ) {}
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
107         QValueListIterator( NodePtr p ) : node( p ) {}
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
570           for (entry *dirEntry=listres.readdirres_u.reply.entries;dirEntry!=0;dirEntry=dirEntry->nextentry)
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
849         if ( d->deref() ) {
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
850             if ( d != shared_null )
(gdb)
851                 d->deleteSelf();
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
53          bool deref()        { return !--count; }
(gdb)
849         if ( d->deref() ) {
(gdb)
850             if ( d != shared_null )
(gdb)
851                 d->deleteSelf();
(gdb)
572              if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
(gdb)
573                 filesToList.append(dirEntry->name);
(gdb)
565         void detach() { if ( sh->count > 1 ) detachInternal(); }
(gdb)
107         QValueListIterator( NodePtr p ) : node( p ) {}
(gdb)
529         iterator append( const T& x ) { detach(); return sh->insert( end(), x ); }
(gdb)
Comment 5 Peter Faasse 2008-07-12 13:09:24 UTC
Mandriva 2008.1 (kde-3.5.9) also has the same problem, with the same target (nfs-exported) directory ;-) It has the appearance that is not be an 'artefact' of my build of kde ;-) It could still be the result of the way i 'export' the nfs-dir though.
Comment 6 Peter Faasse 2008-07-12 16:54:13 UTC
I think i've got a test-pattern now: It seems related to the number of files in a directory: I made an empty test-directory as a subdir of one of these exported nfs-dirs. 

With a 

for i in `seq 1 200`; do touch $i; done

i made 200 bogus files in the directory. That browses ok with konqueror. If -however- i increase the number of files to 210, konqueror 'hangs' when i attempt to browse the subdir, and 'top' shows a kio_nfs process that goes 'berserk' w.r.t. memory usage. 

Would this be a good point to 'call in the troops'? 
Comment 7 Peter Faasse 2008-07-13 10:33:23 UTC
I've opened a new bug-report (Bug 166379), with the result of my further experiments/debugging results, including a fix that seems to work.