Samstag, 13. September 2008

ZSH Patch gegen fieses Memory Leak

Ich bin neulich auf einen unschönen Bug in ZSH gestoßen. Bei aktiviertem compinit wird bei jeder Vervollständigung ein Segment anonymer Speicher angelegt und nicht wieder richtig freigegeben. Ein kleines dtrace Skript hat das Problem entlarvt.

#!/usr/sbin/dtrace -s

BEGIN
{
printf("\nTarget is : %d\nSegement is %X\n",$target, $1);
}

syscall::mmap64:return
/arg1 == $1 && pid == $target/
{
printf("mmap returns: %x",arg1);
self->triggered = 1;
}

pid$target:zsh:dupstring:return
/self->triggered == 1/
{
/*printf("Dupstring: %s",copyinstr(arg1));*/
self->triggered = 0;
}

syscall::mmap64:entry
/pid == $target/
{
printf("mmap size: %d",arg1);
}

syscall::munmap:entry
/arg0 == $1 && pid == $target/
{
printf("munmap size: %d\n",arg1);
ustack();
self->munmapping = 1;
}

syscall::munmap:return
/self->munmapping/
{
printf("Result of munmapping the segment in question was: %d",arg1);
self->munmapping = 0;
}

fbt::as_removeseg:entry
/execname == "zsh" && ((struct seg*)arg1)->s_base == (caddr_t)$1/
{
printf("\nGot removed");
ustack();
stack();
exit(0);
}

fbt::as_addseg:entry
/execname == "zsh" && ((struct seg*)arg1)->s_base == (caddr_t)$1/
{
printf("\nGot added");
ustack();
stack();
}

Danke an das ZSH-Team für das Überprüfen meines Patches.

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;

Keine Kommentare: