active index mismatch in heap?

Marc Lehmann schmorp at schmorp.de
Sun Feb 27 08:38:10 CET 2011


On Sat, Feb 26, 2011 at 11:27:10PM -0600, Brandon Black <blblack at gmail.com> wrote:
> Assertion '("libev: active index mismatch in heap", ((W)((heap
> [i]).w))->active == i)' failed in verify_heap() at ./libev/ev.c:1978
> 
> At this point I'm just looking for some pointers to help me track down
> what's going on: is this generally likely to be an application bug on
> my part (I am using the public API only), or should I be looking more
> at libev itself?

Could be anywhere - what it means is that watchers often (and timers
specifically) store the array index of where they are stored in the ->active
member.

The assert means that the watcher at index i doesn't say it is at index i
(but somewhere else).

Could have lots of reasons - a bug in the heap code, a thread race
condition, something corrupting memory specifically, the index value) and
maybe other reasons.

> Is there some likely stupid error I could be making in my use of the
> ev_timer API that would lead to this assert, that I could double-check
> the code for specifically?

Yes, but there are lots of possibilities. If you use threads, then a
possibility would be that you stop the watcher in another thread. It could
also be that you free an active watcher.

You could prepend an if statement to the assert check and log the value
of i and the value of ev_active (ANHE_w (i)). If i is somewhere between 1 and
roughly the numebr of active watchers, then it is at leats valid, and the bug
migth be timer mismanagement. If it's some widely different value then it's
likely memory corruption. If it's 0, then it could be a thread race.

However, that is all just "coulds" - every value could be any bug.

As for a bug in the heap manegement itself, I would say it's unlikely, as
that assert only checks whether the active value mismatches, and the only
assignments are:

      heap [k] = *minpos;
      ev_active (ANHE_w (*minpos)) = k;

  heap [k] = he;
  ev_active (ANHE_w (he)) = k;

      heap [k] = heap [c];
      ev_active (ANHE_w (heap [k])) = k;

  heap [k] = he;
  ev_active (ANHE_w (he)) = k;

      heap [k] = heap [p];
      ev_active (ANHE_w (heap [k])) = k;

  heap [k] = he;
  ev_active (ANHE_w (he)) = k;

Which makes explaining mismatches much harder. That leaves non-heap code
that might or might not manipulate ev_active.

As a first step, I would log the offending values of i and ev_active at
position i, and look for thread races, or forgetting to stop a watcher and
then reusing it. (e.g. free (), but also stuff like calling ev_timer_init
on an active timer).

-- 
                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      schmorp at schmorp.de
      -=====/_/_//_/\_,_/ /_/\_\



More information about the libev mailing list