Tom Lane wrote: > What is happening is that autovacuum_do_vac_analyze contains > > old_cxt = MemoryContextSwitchTo(AutovacMemCxt); > ... > vacuum(vacstmt, relids); > ... > MemoryContextSwitchTo(old_cxt); > > and at the time it is called by process_whole_db, CurrentMemoryContext > points at TopTransactionContext. Which gets destroyed because vacuum() > internally finishes that transaction and starts a new one. When we > come out of vacuum(), CurrentMemoryContext again points at > TopTransactionContext, but *its not the same one*. The closing > MemoryContextSwitchTo is installing a stale pointer, which then remains > active into CommitTransaction. It's a wonder this code ever works. Hmm, in retrospect this is pretty obviously buggy. I can't say that it's that easy for me to reproduce it though; I definitely can't make it crash. Maybe by sheer luck, the new TopTransactionContext pointer points to the same memory area that the old was stored in. I think this patch should fix it. Justin, would you try it and report back? I would commit it right away since it seems simple enough, but since I can't reproduce the crash, I prefer external confirmation first :-) -- Alvaro Herrera http://www.CommandPrompt.com/ PostgreSQL Replication, Consulting, Custom Development, 24x7 support
Index: src/backend/postmaster/autovacuum.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/postmaster/autovacuum.c,v retrieving revision 1.5.2.8 diff -c -p -r1.5.2.8 autovacuum.c *** src/backend/postmaster/autovacuum.c 17 Jan 2008 23:47:07 -0000 1.5.2.8 --- src/backend/postmaster/autovacuum.c 17 Jan 2009 04:08:44 -0000 *************** autovacuum_do_vac_analyze(List *relids, *** 925,937 **** bool freeze) { VacuumStmt *vacstmt; - MemoryContext old_cxt; /* * The node must survive transaction boundaries, so make sure we create it * in a long-lived context */ ! old_cxt = MemoryContextSwitchTo(AutovacMemCxt); vacstmt = makeNode(VacuumStmt); --- 925,936 ---- bool freeze) { VacuumStmt *vacstmt; /* * The node must survive transaction boundaries, so make sure we create it * in a long-lived context */ ! MemoryContextSwitchTo(AutovacMemCxt); vacstmt = makeNode(VacuumStmt); *************** autovacuum_do_vac_analyze(List *relids, *** 957,963 **** vacuum(vacstmt, relids); pfree(vacstmt); ! MemoryContextSwitchTo(old_cxt); } /* --- 956,964 ---- vacuum(vacstmt, relids); pfree(vacstmt); ! ! /* Make sure we end up pointing to a valid memory context at exit */ ! MemoryContextSwitchTo(TopTransactionContext); } /*
-- Sent via pgsql-general mailing list (pgsql-general@xxxxxxxxxxxxxx) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-general