Bug in new buffering GiST build code

Heikki Linnakangas <heikki.linnakangas@enterprisedb.com>

From: Heikki Linnakangas <heikki.linnakangas@enterprisedb.com>
To: PostgreSQL-development <pgsql-hackers@postgreSQL.org>
Cc: Alexander Korotkov <aekorotkov@gmail.com>
Date: 2012-05-18T16:27:32Z
Lists: pgsql-hackers

Attachments

I bumped into a bug in the new buffering GiST build code. I did this:

create table gisttest (t text);
insert into gisttest select 
a||'fooooooooooooooooooooooooooooooooooooooooooooooo' from 
generate_series(1,10000000) a;

create index i_gisttest on gisttest using gist (t collate "C") WITH 
(fillfactor=10);

After a while, this segfaults.

I debugged this, and traced this into a bug in the 
gistRelocateBuildBuffersOnSplit() function. It splits a node buffer into 
two (or more) node buffers, when the corresponding index page is split. 
It first makes a copy of the old GISTNodeBuffer struct, and then 
repurposes the struct to hold the new buffer for the new leftmost page 
of the split. The temporary copy of the old page is only needed while 
the function moves all the tuples from the old buffer into the new 
buffers, after that it can be discarded. The temporary copy of the 
struct is kept in the stack. However, the temporary copy can find its 
way into the list of "loaded buffers". After the function exits, and 
it's time to unload all the currently loaded buffers, you get a segfault 
because the pointer now points to garbage. I think the reason this 
doesn't always crash is that the copy in the stack usually still happens 
to be valid enough that gistUnloadNodeBuffer() just skips it.

I'll commit the attached fix for that, marking the temporary copy 
explicitly, so that we can avoid leaking it into any long-lived data 
structures.

After fixing that, however, I'm now getting another error, much later in 
the build process:

ERROR:  failed to re-find parent for block 123002
STATEMENT:  create index i_gisttest on gisttest using gist (t collate 
"C") WITH (fillfactor=10);

I'll continue debugging that, but it seems to be another, unrelated, bug.

-- 
   Heikki Linnakangas
   EnterpriseDB   http://www.enterprisedb.com