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__