| Bug bnc#520598 : memory leak in ksh | | From: David Korn | Subject: Re: Re: [ast-developers] Re: Memory leak in ksh upto 2009-06-30 | | I started looking at this before I went on vacation. Here are changes | I makde to sh/nvdisc.c that eliminate much of the problem. | Note, that line numbers differ because my version doesn't have | the copyright notices. | --- src/cmd/ksh93/sh/nvdisc.c +++ src/cmd/ksh93/sh/nvdisc.c 2009-07-09 18:57:02.000000000 +0200 @@ -573,13 +573,14 @@ Namfun_t *nv_clone_disc(register Namfun_ { register Namfun_t *nfp; register int size; + if(!fp->disc && !fp->next && (fp->nofree&1)) + return(fp); if(!(size=fp->dsize) && (!fp->disc || !(size=fp->disc->dsize))) size = sizeof(Namfun_t); if(!(nfp=newof(NIL(Namfun_t*),Namfun_t,1,size-sizeof(Namfun_t)))) return(0); memcpy(nfp,fp,size); - if(flags&NV_COMVAR) - nfp->nofree &= ~1; + nfp->nofree &= ~1; nfp->nofree |= (flags&NV_RDONLY)?1:0; return(nfp); } | | From: David Korn | Subject: Re: Re: [ast-developers] Re: Memory leak in ksh upto 2009-06-30 | | This change eliminates about 80% of the leak in the case that you sent. | I will send another change to eliminate the rest. | --- src/cmd/ksh93/sh/xec.c +++ src/cmd/ksh93/sh/xec.c 2009-08-06 18:07:12.000000000 +0200 @@ -352,7 +352,12 @@ static void put_level(Namval_t* np,const int16_t level, oldlevel = (int16_t)nv_getnum(np); nv_putv(np,val,flags,fp); if(!val) + { + fp = nv_stack(np, NIL(Namfun_t*)); + if(fp && !fp->nofree) + free((void*)fp); return; + } level = nv_getnum(np); if(level<0 || level > lp->maxlevel) { | | From: David Korn | Subject: Re: Re: [ast-developers] Re: Memory leak in ksh upto 2009-06-30 | | Here is another fix that should eliminate the leak from the | script that you sent. | --- src/cmd/ksh93/bltins/read.c +++ src/cmd/ksh93/bltins/read.c 2009-08-06 19:00:24.000000000 +0200 @@ -67,9 +67,14 @@ int b_read(int argc,char *argv[], void * int save_prompt, fixargs=((Shbltin_t*)extra)->invariant; struct read_save *rp; static char default_prompt[3] = {ESC,ESC}; + rp = (struct read_save*)(((Shbltin_t*)extra)->data); if(argc==0) + { + if(rp) + free((void*)rp); return(0); - if(rp = (struct read_save*)(((Shbltin_t*)extra)->data)) + } + if(rp) { flags = rp->flags; timeout = rp->timeout; | | From: David Korn | Subject: Re: Re: [ast-developers] Re: Memory leak in ksh upto 2009-06-30 | | I hope that I finally got it. Here are the changes to init.c and subshell.c | --- src/cmd/ksh93/sh/init.c +++ src/cmd/ksh93/sh/init.c 2009-08-10 16:05:02.000000000 +0200 @@ -445,10 +445,18 @@ static void put_cdpath(register Namval_t static void put_ifs(register Namval_t* np,const char *val,int flags,Namfun_t *fp) { register struct ifs *ip = (struct ifs*)fp; + Shell_t *shp; ip->ifsnp = 0; + if(!val) + { + fp = nv_stack(np, NIL(Namfun_t*)); + if(fp && !fp->nofree) + free((void*)fp); + } if(val != np->nvalue.cp) nv_putv(np, val, flags, fp); - + if(!val && !(flags&NV_CLONE) && (fp=np->nvfun) && !fp->disc && (shp=(Shell_t*)(fp->last))) + nv_stack(np,&((Init_t*)shp->init_context)->IFS_init.hdr); } /* @@ -522,7 +530,7 @@ static void put_seconds(register Namval_ fp = nv_stack(np, NIL(Namfun_t*)); if(fp && !fp->nofree) free((void*)fp); - nv_unset(np); + nv_putv(np, val, flags, fp); return; } if(!np->nvalue.dp) --- src/cmd/ksh93/sh/subshell.c +++ src/cmd/ksh93/sh/subshell.c 2009-08-10 16:05:19.000000000 +0200 @@ -254,7 +254,7 @@ Namval_t *sh_assignok(register Namval_t Namarr_t *ap; int save; /* don't bother with this */ - if(!sp->shpwd || (nv_isnull(np) && !add)) + if(!sp->shpwd || (nv_isnull(np) && !add) || np==SH_LEVELNOD) return(np); /* don't bother to save if in newer scope */ if(!(rp=shp->st.real_fun) || !(dp=rp->sdict)) @@ -334,7 +334,7 @@ static void nv_restore(struct subshell * continue; if(nv_isarray(mp)) nv_putsub(mp,NIL(char*),ARRAY_SCAN); - _nv_unset(mp,NV_RDONLY); + _nv_unset(mp,NV_RDONLY|NV_CLONE); if(nv_isarray(np)) { nv_clone(np,mp,NV_MOVE); @@ -346,7 +346,11 @@ static void nv_restore(struct subshell * mp->nvfun = np->nvfun; mp->nvflag = np->nvflag; if(nv_cover(mp)) - nv_putval(mp, nv_getval(np),0); + { + nv_putval(mp, nv_getval(np),np->nvflag|NV_NOFREE); + if(!nv_isattr(np,NV_NOFREE)) + nv_offattr(mp,NV_NOFREE); + } else mp->nvalue.cp = np->nvalue.cp; np->nvfun = 0;