RHEL5 x64, skiplist statuscache SIGV

Michael Glad glad at daimi.au.dk
Mon Sep 24 04:26:11 EDT 2007


The problems seem to boil down to what happens when one tries to delete
a key from an empty skiplist db:

bash-3.00$ touch /tmp/foo.db
bash-3.00$ /usr/lib/cyrus-imapd/cyr_dbtool  /tmp/foo.db skiplist show
bash-3.00$ ls -l /tmp/foo.db
-rw-r--r--  1 cyrus mail 144 Sep 24 10:03 /tmp/foo.db
bash-3.00$ /usr/lib/cyrus-imapd/cyr_dbtool  /tmp/foo.db skiplist delete bar
Segmentation fault

This was done on RHEL4/x32. The same happens on RHEL5/x64.

As I wrote below, it seems that the skiplist code in this case tries to 
extract skiplist pointers from the db header.

	- Michael

On Mon, Sep 24, 2007 at 12:25:55PM +1000, Bron Gondwana wrote:
> 
> On Sun, 23 Sep 2007 21:58:57 +0200, "Michael Glad" <glad at daimi.au.dk> said:
> > 
> > Hello Bron, I've tested Cyrus 2.3.9 + your FM patches as of September 20
> > on a RHEL5 x64 Opteron virtual machine. 
> 
> We don't have any experience (yet) with 64 bit.  I believe it's less
> well tested.
> 
> > As I'm a BDB skepticist  I use skiplists where ever possible including 
> > the statuscache.
> 
> >From memory it's not a good match because of the various strengths and
> weaknesses of the the database methods used.  Skiplist is good for heavy
> read loads, not so good for heavy write loads.
> 
> > But Imapd SIGV's in the skiplist mydelete routine (invoked from
> > statuscache_invalidate) when the first 'select INBOX' command is
> > received.
> > 
> > I've looked into the cause and would to hear your opinion before I
> > post the info below to the devel list.
> > 
> > It seems to me that the skiplist routine is to blame. The SIGV
> > arises from line 1305:
> > 
> > 	newoffset = htonl(FORWARD(ptr, i));
> > 
> > But ptr at the time of the crash points to db->map_base which is the
> > initial skiplist header => Kaboom.
> > 
> > When I apply the patch:
> > 
> > @@ -1292,6 +1292,11 @@
> >      ptr = find_node(db, key, keylen, updateoffsets);
> >      if (ptr == db->map_base ||
> >         !db->compar(KEY(ptr), KEYLEN(ptr), key, keylen)) {
> > +/* start glad */
> > +if(ptr == db->map_base) {
> > +       ptr = DUMMY_PTR(db);
> > +}
> > +/* end glad */
> >         /* gotcha */
> >         offset = ptr - db->map_base;
> > 
> > things doesn't SIGV and output from
> > 
> > 	/usr/lib/cyrus-imapd/cyr_dbtool /var/lib/imap/statuscache.db skiplist show
> > 
> > looks sensible -- it is partly garbled on my nonpatched RHEL4 
> > x32 production system.
> 
> 
> I have CC'd this to the cyrus development list, as there are probably people with
> more skiplist and 64 bit programming experience who can tell you if this is the
> right approach, and hopefully push the fix into the next Cyrus release!
> 
> Bron.
> -- 
>   Bron Gondwana
>   brong at fastmail.fm


More information about the Cyrus-devel mailing list