Thread: backend crash with certain statements/tables

backend crash with certain statements/tables

From
Jeff Bohmer
Date:
Reproduced in PG 7.4.1 on ...

OS X Server 10.2.8
OS X 10.2.8
RHL 9 (2.4.20-30.9)

Running any of these statements on my database causes the backend to
crash (example from PG log below):

create temp table foo as select * from server_prefs limit 1;
create table foo as select * from server_prefs limit 1;
create temp table foo as select * from agency_dbs limit 1;
create table foo as select * from agency_dbs limit 1;


All of these statements produce expected results (no crash):

create temp table foo as select * from c_group limit 1;
create table foo as select * from c_group limit 1;
create table foo as select * from server_prefs;
create table foo as select * from agency_dbs;
select * from server_prefs limit 1;
select * from agency_dbs limit 1;


Attached is a file that creates a database and only the server_prefs
table and then reproduces the crash for me on both OS X and Linux
when I run it like:

    psql -d template1 -U postgres -f pg_crash

Thanks,
- Jeff



2004-03-01 10:32:24 [471] LOG:  connection received: host=[local] port=
2004-03-01 10:32:24 [471] LOG:  connection authorized: user=username
database=cos
2004-03-01 10:32:34 [471] LOG:  statement: create temp table foo as
select * from server_prefs limit 1;
2004-03-01 10:32:35 [19913] LOG:  server process (PID 471) was
terminated by signal 10
2004-03-01 10:32:35 [19913] LOG:  terminating any other active server processes
2004-03-01 10:32:35 [429] WARNING:  terminating connection because of
crash of another server process
DETAIL:  The postmaster has commanded this server process to roll
back the current transaction and exit, because another server process
exited abnormally and possibly corrupted shared memory.
HINT:  In a moment you should be able to reconnect to the database
and repeat your command.
2004-03-01 10:32:35 [474] LOG:  connection received: host=[local] port=
2004-03-01 10:32:35 [474] FATAL:  the database system is in recovery mode
2004-03-01 10:32:35 [19913] LOG:  all server processes terminated;
reinitializing
2004-03-01 10:32:35 [475] LOG:  database system was interrupted at
2004-03-01 10:27:58 MST
2004-03-01 10:32:35 [475] LOG:  checkpoint record is at 5/1350BF6C
2004-03-01 10:32:35 [475] LOG:  redo record is at 5/1350BF6C; undo
record is at 0/0; shutdown TRUE
2004-03-01 10:32:35 [475] LOG:  next transaction ID: 374025; next OID: 46414656
2004-03-01 10:32:35 [475] LOG:  database system was not properly shut
down; automatic recovery in progress
2004-03-01 10:32:35 [475] LOG:  redo starts at 5/1350BFAC
2004-03-01 10:32:35 [475] LOG:  unexpected pageaddr 5/9570000 in log
file 5, segment 19, offset 5701632
2004-03-01 10:32:35 [475] LOG:  redo done at 5/1356EB8C
2004-03-01 10:32:38 [475] LOG:  database system is ready


--

Jeff Bohmer
VisionLink, Inc.
_________________________________
303.402.0170
www.visionlink.org
_________________________________
People. Tools. Change. Community.
Attachment

Re: backend crash with certain statements/tables

From
Tom Lane
Date:
Jeff Bohmer <bohmer@visionlink.org> writes:
> Running any of these statements on my database causes the backend to
> crash (example from PG log below):

Crash confirmed here.  Seems to be a side-effect of the 7.4 optimization
that tries to avoid "unnecessary" projection steps.  In the "SELECT *
FROM foo LIMIT" case, the scan plan decides it need not do projection,
but actually one must occur (else heap_insert will scribble on the
source table :-().  The junkfilter code in execMain.c is supposed to
catch this situation, but it's fooled by the presence of a LIMIT step.
There may be some related cases, need to think more.

I should have a patch later today.

            regards, tom lane

Re: backend crash with certain statements/tables

From
Jeff Bohmer
Date:
>
>I should have a patch later today.

Great!  I'd like to try out the patch when it's ready.

Thanks,
- Jeff
--

Jeff Bohmer
VisionLink, Inc.
_________________________________
303.402.0170
www.visionlink.org
_________________________________
People. Tools. Change. Community.

Re: backend crash with certain statements/tables

From
Tom Lane
Date:
Jeff Bohmer <bohmer@visionlink.org> writes:
> Great!  I'd like to try out the patch when it's ready.

Here ya go.

            regards, tom lane

Index: src/backend/executor/execAmi.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/executor/execAmi.c,v
retrieving revision 1.75.4.1
diff -c -r1.75.4.1 execAmi.c
*** src/backend/executor/execAmi.c    18 Dec 2003 20:21:53 -0000    1.75.4.1
--- src/backend/executor/execAmi.c    2 Mar 2004 18:52:18 -0000
***************
*** 348,350 ****
--- 348,415 ----
              return false;
      }
  }
+
+ /*
+  * ExecMayReturnRawTuples
+  *        Check whether a plan tree may return "raw" disk tuples (that is,
+  *        pointers to original data in disk buffers, as opposed to temporary
+  *        tuples constructed by projection steps).  In the case of Append,
+  *        some subplans may return raw tuples and others projected tuples;
+  *        we return "true" if any of the returned tuples could be raw.
+  *
+  * This must be passed an already-initialized planstate tree, because we
+  * need to look at the results of ExecAssignScanProjectionInfo().
+  */
+ bool
+ ExecMayReturnRawTuples(PlanState *node)
+ {
+     /*
+      * At a table scan node, we check whether ExecAssignScanProjectionInfo
+      * decided to do projection or not.  Most non-scan nodes always project
+      * and so we can return "false" immediately.  For nodes that don't
+      * project but just pass up input tuples, we have to recursively
+      * examine the input plan node.
+      *
+      * Note: Hash and Material are listed here because they sometimes
+      * return an original input tuple, not a copy.  But Sort and SetOp
+      * never return an original tuple, so they can be treated like
+      * projecting nodes.
+      */
+     switch (nodeTag(node))
+     {
+         /* Table scan nodes */
+         case T_SeqScanState:
+         case T_IndexScanState:
+         case T_TidScanState:
+         case T_SubqueryScanState:
+         case T_FunctionScanState:
+             if (node->ps_ProjInfo == NULL)
+                 return true;
+             break;
+
+         /* Non-projecting nodes */
+         case T_HashState:
+         case T_MaterialState:
+         case T_UniqueState:
+         case T_LimitState:
+             return ExecMayReturnRawTuples(node->lefttree);
+
+         case T_AppendState:
+         {
+             AppendState *appendstate = (AppendState *) node;
+             int            j;
+
+             for (j = 0; j < appendstate->as_nplans; j++)
+             {
+                 if (ExecMayReturnRawTuples(appendstate->appendplans[j]))
+                     return true;
+             }
+             break;
+         }
+
+         /* All projecting node types come here */
+         default:
+             break;
+     }
+     return false;
+ }
Index: src/backend/executor/execMain.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/executor/execMain.c,v
retrieving revision 1.220.2.1
diff -c -r1.220.2.1 execMain.c
*** src/backend/executor/execMain.c    22 Jan 2004 02:23:35 -0000    1.220.2.1
--- src/backend/executor/execMain.c    2 Mar 2004 18:52:18 -0000
***************
*** 665,674 ****
      /*
       * Initialize the junk filter if needed.  SELECT and INSERT queries
       * need a filter if there are any junk attrs in the tlist.    INSERT and
!      * SELECT INTO also need a filter if the top plan node is a scan node
!      * that's not doing projection (else we'll be scribbling on the scan
!      * tuple!)    UPDATE and DELETE always need a filter, since there's
!      * always a junk 'ctid' attribute present --- no need to look first.
       */
      {
          bool        junk_filter_needed = false;
--- 665,674 ----
      /*
       * Initialize the junk filter if needed.  SELECT and INSERT queries
       * need a filter if there are any junk attrs in the tlist.    INSERT and
!      * SELECT INTO also need a filter if the plan may return raw disk tuples
!      * (else heap_insert will be scribbling on the source relation!).
!      * UPDATE and DELETE always need a filter, since there's always a junk
!      * 'ctid' attribute present --- no need to look first.
       */
      {
          bool        junk_filter_needed = false;
***************
*** 689,706 ****
                      }
                  }
                  if (!junk_filter_needed &&
!                     (operation == CMD_INSERT || do_select_into))
!                 {
!                     if (IsA(planstate, SeqScanState) ||
!                         IsA(planstate, IndexScanState) ||
!                         IsA(planstate, TidScanState) ||
!                         IsA(planstate, SubqueryScanState) ||
!                         IsA(planstate, FunctionScanState))
!                     {
!                         if (planstate->ps_ProjInfo == NULL)
!                             junk_filter_needed = true;
!                     }
!                 }
                  break;
              case CMD_UPDATE:
              case CMD_DELETE:
--- 689,697 ----
                      }
                  }
                  if (!junk_filter_needed &&
!                     (operation == CMD_INSERT || do_select_into) &&
!                     ExecMayReturnRawTuples(planstate))
!                     junk_filter_needed = true;
                  break;
              case CMD_UPDATE:
              case CMD_DELETE:
Index: src/include/executor/executor.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/executor/executor.h,v
retrieving revision 1.102.2.2
diff -c -r1.102.2.2 executor.h
*** src/include/executor/executor.h    22 Jan 2004 02:23:35 -0000    1.102.2.2
--- src/include/executor/executor.h    2 Mar 2004 18:52:19 -0000
***************
*** 36,41 ****
--- 36,42 ----
  extern void ExecRestrPos(PlanState *node);
  extern bool ExecSupportsMarkRestore(NodeTag plantype);
  extern bool ExecSupportsBackwardScan(Plan *node);
+ extern bool ExecMayReturnRawTuples(PlanState *node);

  /*
   * prototypes from functions in execGrouping.c

Re: backend crash with certain statements/tables

From
Jeff Bohmer
Date:
>Jeff Bohmer <bohmer@visionlink.org> writes:
>>  Great!  I'd like to try out the patch when it's ready.
>
>Here ya go.


Works for me on OS X and Linux.

Thank you very much!

- Jeff
--

Jeff Bohmer
VisionLink, Inc.
_________________________________
303.402.0170
www.visionlink.org
_________________________________
People. Tools. Change. Community.