assertion failures

Pascal Bourguignon kaffe@rufus.w3.org
Wed, 29 Jul 98 04:51:23 +0200


> From: Godmar Back <gback@cs.utah.edu>
> Subject: Re: assertion failures
> Date: Tue, 28 Jul 1998 16:48:25 -0600 (MDT)
> 
> > 
> > > From: Archie Cobbs <archie@whistle.com>
> > > Subject: assertion failures
> > > To: kaffe@rufus.w3.org
> > > Date: Mon, 27 Jul 1998 19:09:32 -0700 (PDT)
> > >
> > > I'm getting assertion failures in kaffe-snap Mon Jul 27 
> > > 08:02:00. 1998 This is on FreeBSD.
> > >
> > > My particular application is trying to use threads, which seems
> > > to trigger the problem.
> > >
> > >   #0  0x200e3851 in kill ()
> > >   #1  0x200e2ee4 in abort ()
> > >   #2  0x200bcbd2 in __assert ()
> > >   #3  0x2001cbc7 in gc_heap_malloc (sz=20) at 
> > >                                        ./mem/gc-mem.c:267
> > >   #4  0x2001ba69 in gcMalloc (size=12, fidx=2) at
> > >                                        mem/gc-incremental.c:678
> > >
> > 
> > 
> > I've identified and corrected a bug in gc-mem.c regarding the  
> > assertion blk->free!=0 that was not enforced (and it could not 
> > be).
> 
>  Pascal,
> 
> The backtrace you quote in your mail was for the recursive stack
> overflow problem, so I don't think your fix addresses it.
> 
> Could you explain what your fix does and why that assertion is not 
> valid?  Do you have a reproducible test case that blows up?


The problem is around these lines:

242          /* No available objects? Allocate some more */
243          mptr = &freelist[lnr].list;
244          if (*mptr != 0) {
245              blk = *mptr;
246              assert(blk->free != 0);
247  DBG(GCALLOC,        dprintf("gc_heap_malloc: freelist %d at %p\n", sz, *mptr);)
248          }
249          else {
250              blk = gc_small_block(nsz);
251              if (blk == 0) {
252                  nsz = gc_pgsize;
253                  goto nospace;
254              }
255              blk->nfree = *mptr;
256              *mptr = blk;
257
258  DBG(GCALLOC,        dprintf("gc_heap_malloc: small block %d at %p\n", sz, *mptr);)
259          }
260
261          /* Unlink free one and return it */
262          mem = blk->free;
263  #if defined(GC_DEBUG)
264          assert(blk->magic == GC_MAGIC);
265          assert((uintp)mem >= (uintp)blk &&
266              (uintp)mem < (uintp)blk + gc_pgsize);
267          assert(mem->next == 0 || ((uintp)mem->next >= (uintp)blk &&
268              (uintp)mem->next < (uintp)blk + gc_pgsize));
269  #endif
270          blk->free = mem->next;

The assertion that is not enforced by the version 1.0b1 is on line 246. It is not enforced because of line 270. The assertion on line 267 shows that it is valid for mem->next to be 0. In that case, blk->free becomes 0, and the next time we try to allocate a bloc from the same mptr, the assertion on line 246 is invalidated. After having studied the remainder of the gc-*.[hc] files, I corrected the problem by replacing the test on line 244 with :

new 244:	if ((*mptr != 0) /*PJB: Let's ensure that too: */ &&(blk->free!=0)) {

Then, on line 260, we can assert that blk->free!=0.



Now, the backtrace indicates that it's the assert on line 267 that is invalidated. That should be another problem. I provided my patch because I refered the line 267 in my new version of gc-mem.c, and it was nearer then to the assert of line 246, but it was probably not relevant.


__Pascal Bourguignon__