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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general