Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT sources DOT redhat DOT com Delivered-To: mailing list cygwin AT sources DOT redhat DOT com Message-ID: <2E300728EEF9D3119D8000E018C1864F5E427A@gemini> From: "Mortimer, Andy" To: "'cygwin AT sourceware DOT cygnus DOT com'" Subject: patch for ash mem fault Date: Wed, 27 Sep 2000 10:51:34 -0600 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.5.2448.0) Content-Type: multipart/mixed; boundary="----_=_NextPart_000_01C028A3.2B0BBD06" ------_=_NextPart_000_01C028A3.2B0BBD06 Content-Type: text/plain; charset="iso-8859-1" Hi all, (I'm not sure who to send this to, because I can't quite work out where ash comes from! Hopefully this is a reasonable first try ...) I think I've found and fixed a segfault in ash 20000823 (from Cygwin). I have a feeling that this has been around since b20 or before -- I definitely saw a similar one there, which I fixed by changing to bash for this particular script -- but I don't have that installed any more to confirm that it's the same one. The problem occurs infrequently, when a large string value (>504 chars, I think!) is assigned to a variable. In ash- source-speak, what happens is that the current stack position is saved via a call to setstackmark, but then before it is freed again in popstackmark, a call to growstackblock moves the stack block which has been saved. Then when the time comes to free it, the free is passed an invalid pointer, and basically, it all goes horribly wrong. (All these routines are in memalloc.c) The attached patch adds a new member to the stack_block structure which is initially set to zero, but is incremented if setstackmark is called on a particular stack_block. If this member is non-zero in growstackblock, even if no data is actually allocated in that block, it will still go ahead and create another one and leave the previous one in place. This is all at the cost of an extra 4 bytes in a stack_block, but looking at the average length of the block chain for the sorts of runs I've been doing (about 4 or 5 for most of the time, I think), I don't expect that this is a problem. Wiser minds than mine may prevail, however. I've checked that this fixes the problem I was having; however, I haven't done much more testing than that single (admittedly many thousand line) script. Have fun! Andy -- Andy Mortimer, CFX-5 Architecture and Infrastructure Team andy DOT mortimer AT aeat DOT com ------_=_NextPart_000_01C028A3.2B0BBD06 Content-Type: application/octet-stream; name="memalloc.diff" Content-Disposition: attachment; filename="memalloc.diff" *** memalloc.c.orig Wed Sep 27 17:43:39 2000 --- memalloc.c Wed Sep 27 17:21:57 2000 *************** *** 106,118 **** * * The size 504 was chosen because the Ultrix malloc handles that size * well. */ ! #define MINSIZE 504 /* minimum size of a block */ struct stack_block { struct stack_block *prev; char space[MINSIZE]; }; --- 106,121 ---- * * The size 504 was chosen because the Ultrix malloc handles that size * well. + * + * Reduced to 500 now I've added an extra int -- andy DOT mortimer AT zetnet DOT co DOT uk */ ! #define MINSIZE 500 /* minimum size of a block */ struct stack_block { struct stack_block *prev; + int refcnt; char space[MINSIZE]; }; *************** *** 143,148 **** --- 146,152 ---- sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize); sp->prev = stackp; + sp->refcnt = 0; stacknxt = sp->space; stacknleft = blocksize; stackp = sp; *************** *** 176,183 **** mark->stackp = stackp; mark->stacknxt = stacknxt; mark->stacknleft = stacknleft; - } void popstackmark(mark) --- 180,188 ---- mark->stackp = stackp; mark->stacknxt = stacknxt; mark->stacknleft = stacknleft; + stackp->refcnt++; + } void popstackmark(mark) *************** *** 186,191 **** --- 191,197 ---- struct stack_block *sp; INTOFF; + mark->stackp->refcnt--; while (stackp != mark->stackp) { sp = stackp; stackp = sp->prev; *************** *** 220,226 **** oldspace = stacknxt; oldlen = stacknleft; ! if (stacknxt == stackp->space && stackp != &stackbase) { INTOFF; sp = stackp; stackp = sp->prev; --- 226,233 ---- oldspace = stacknxt; oldlen = stacknleft; ! if (stacknxt == stackp->space && stackp != &stackbase ! && !stackp->refcnt) { INTOFF; sp = stackp; stackp = sp->prev; ------_=_NextPart_000_01C028A3.2B0BBD06 Content-Type: text/plain; charset=us-ascii -- Want to unsubscribe from this list? Send a message to cygwin-unsubscribe AT sourceware DOT cygnus DOT com ------_=_NextPart_000_01C028A3.2B0BBD06--