Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH] compsys maps anonymous memory and never frees it



On Sunday 07 September 2008, xRaich[o]²x wrote:
> 
> Bart Schaefer wrote:
> > On Sep 4,  1:04am, =?ISO-8859-1?Q?Bj=F6rn_Herzig?= wrote:
> > }
> > } I looked at the problem a little closer. Zsh does not call mmap to
> > } allocate them and they dont get allocated when completion happens but
> > } when the next command gets issued.
> >
> > If this is true, then this is something happening down in the library
> > or kernel implementation of fork() and is out of zsh's control.
> >
> > Did you build zsh yourself?  Can you check config.h for USE_MMAP ?
> > If USE_MMAP is defined then anytime zsh parses a command it will have
> > called mmap() to allocate zsh-heap space.  You can try reconfiguring
> > with --enable-zsh-mem and then check the pmap behavior again.
> >
> > } So in my example the new maps got added to the process' address space
> > } when i executed pmap, but the same happens with any other programm.
> > } Builtins however are an exception. So things start to go wrong when it
> > } comes to forking.
> >
> > If you run pmap from another shell window rather than executing it
> > from within the shell whose map you're examining, does the behavior
> > change at all?
> >
> > My only guess goes something like this:
> >
> > Zsh has mapped memory for the heap during parsing etc.  Those pages
> > have had data written and therefore are marked "dirty".  When fork()
> > is called, those pages become shared address space with the child
> > process.  Zsh munmap()s them later but they aren't returned to the
> > system because the child process is still using them.
> >
> > I'm not really happy with any of these explanations yet.
> >
> >   
> 
> Ok, i found it.... after wandering around in a few deadends and getting 
> some stuff wrong... but well.
> 
> i did the following change to mem.c
> 
> mod_export void
> old_heaps(Heap old)
> {
>     Heap h, n;
> 
>     queue_signals();
>     for (h = heaps; h; h = n) {
>     n = h->next;
>     DPUTS(h->sp, "BUG: old_heaps() with pushed heaps");
> #ifdef USE_MMAP
>     //munmap((void *) h, sizeof(*h));
>     munmap((void *) h, h->size);

Good catch (it was obvious bug)

> #else
>     //zfree(h, sizeof(*h));
>     zfree(h, h->size);

In most other places we are using zfree(h, HEAPSIZE); there is no guarantee
heap is actually of size HEAPSIZE, but that does not matter (second argument
is used only with enable-zsh-mem and serves as plausibility check only).

Here is patch in proper format. It is using HEAPSIZE for consistency:

Index: Src/mem.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/mem.c,v
retrieving revision 1.16
diff -u -p -r1.16 mem.c
--- Src/mem.c   17 May 2008 17:55:38 -0000      1.16
+++ Src/mem.c   7 Sep 2008 09:23:32 -0000
@@ -153,9 +153,9 @@ old_heaps(Heap old)
        n = h->next;
        DPUTS(h->sp, "BUG: old_heaps() with pushed heaps");
 #ifdef USE_MMAP
-       munmap((void *) h, sizeof(*h));
+       munmap((void *) h, h->size);
 #else
-       zfree(h, sizeof(*h));
+       zfree(h, HEAPSIZE);
 #endif
     }
     heaps = old;

Attachment: signature.asc
Description: This is a digitally signed message part.



Messages sorted by: Reverse Date, Date, Thread, Author