pgsql-5622

Version:

8.4.4

Bug Link:

http://archives.postgresql.org/pgsql-bugs/2010-08/msg00275.php

http://postgresql.1045698.n5.nabble.com/BUG-5622-Query-failed-server-closed-the-connection-unexpectedly-td2638757.html

Patch Link:

http://archives.postgresql.org/pgsql-committers/2010-08/msg00237.php

Symptom:

postgresql crashes under certain input(a bunch of sql commands, see below).

Failure type:

segment fault

Is there any log message?

Yes

How it is diagnosed:

We reproduced the failure.

How to reproduce:

http://postgresql.1045698.n5.nabble.com/attachment/2640245/0/bug.sql

Root Cause:

afterTriggerInvokeEvents failed to adjust events->tailfree when truncating

the last chunk of an event list.  This could result in the data being

"de-truncated" by afterTriggerRestoreEventList during a subsequent

subtransaction abort.  Even that wouldn't kill us, because the re-added data

would just be events marked DONE --- unless the data had been partially

overwritten by new events.  Then we might crash, or in any case misbehave

(perhaps fire triggers twice, or fire triggers with the wrong event data).

src/backend/commands/trigger.c

afterTriggerInvokeEvents(AfterTriggerEventList *events,...)

{

                …

                /* Clear the chunk if delete_ok and nothing left of interest */

                if (delete_ok && all_fired_in_chunk)

                 {
                         chunk->freeptr = CHUNK_DATA_START(chunk);
                         chunk->endfree = chunk->endptr;
+
+                         /*
+                          * If it's last chunk, must sync event list's tailfree too.  Note
+                          * that delete_ok must NOT be passed as true if there could be
+                          * stacked AfterTriggerEventList values pointing at this event
+                          * list, since we'd fail to fix their copies of tailfree.
+                          */
+                         if (chunk == events->tail)
+                                 events->tailfree = chunk->freeptr;
                 }

}

#0  afterTriggerCheckState (evtshared=0x40163089) at trigger.c:2850

2850            if ((evtshared->ats_event & AFTER_TRIGGER_DEFERRABLE) == 0)

(gdb) bt

#0  afterTriggerCheckState (evtshared=0x40163089) at trigger.c:2850

#1  0x2f61f4 in afterTriggerMarkEvents (events=0x40163089, move_list=0x0,

    immediate_only=1 '\001') at trigger.c:3219

#2  0x2f76dc in AfterTriggerSetState (stmt=0x40064af0) at trigger.c:4149

#3  0x418250 in standard_ProcessUtility (parsetree=0x40064af0,

    queryString=0x400641a8 "SET CONSTRAINTS ALL IMMEDIATE;", params=0x0,

    isTopLevel=1 '\001', dest=0x40064cd8, completionTag=0x7b03b308 "")

    at utility.c:1226

#4  0x416a70 in ProcessUtility (parsetree=0x40064af0,

    queryString=0x400641a8 "SET CONSTRAINTS ALL IMMEDIATE;", params=0x0,

    isTopLevel=1 '\001', dest=0x40064cd8, completionTag=0x7b03b308 "")

    at utility.c:323

#5  0x415740 in PortalRunUtility (portal=0x400e1fa0, utilityStmt=0x40064af0,

    isTopLevel=1 '\001', dest=0x40064cd8, completionTag=0x7b03b308 "")

    at pquery.c:1191

#6  0x4158f0 in PortalRunMulti (portal=0x400e1fa0, isTopLevel=1 '\001',

    dest=0x40064cd8, altdest=0x40064cd8, completionTag=0x7b03b308 "")

    at pquery.c:1298

#7  0x414f64 in PortalRun (portal=0x400e1fa0, count=2147483647,

    isTopLevel=1 '\001', dest=0x40064cd8, altdest=0x40064cd8,

    completionTag=0x7b03b308 "") at pquery.c:822

#8  0x40e7c0 in exec_simple_query (

    query_string=0x400641a8 "SET CONSTRAINTS ALL IMMEDIATE;")

Pattern to handle:

Signal handler