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.