Fix crash when canceling parallel query
authorPeter Eisentraut <peter_e@gmx.net>
Thu, 1 Feb 2018 22:07:38 +0000 (17:07 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Fri, 16 Feb 2018 21:21:24 +0000 (16:21 -0500)
elog(FATAL) would end up calling PortalCleanup(), which would call
executor shutdown code, which could fail and crash, especially under
parallel query.  This was introduced by
8561e4840c81f7e345be2df170839846814fa004, which did not want to mark an
active portal as failed by a normal transaction abort anymore.  But we
do need to do that for an elog(FATAL) exit.  Introduce a variable
shmem_exit_inprogress similar to the existing proc_exit_inprogress, so
we can tell whether we are in the FATAL exit scenario.

Reported-by: Andres Freund <andres@anarazel.de>
src/backend/storage/ipc/ipc.c
src/backend/utils/mmgr/portalmem.c
src/include/storage/ipc.h

index 2de35efbd4f278a49b401709ae57889671ba51b7..726db7b7f1b9a25ceb44146e6b8041a3528bb53c 100644 (file)
  */
 bool       proc_exit_inprogress = false;
 
+/*
+ * Set when shmem_exit() is in progress.
+ */
+bool       shmem_exit_inprogress = false;
+
 /*
  * This flag tracks whether we've called atexit() in the current process
  * (or in the parent postmaster).
@@ -214,6 +219,8 @@ proc_exit_prepare(int code)
 void
 shmem_exit(int code)
 {
+   shmem_exit_inprogress = true;
+
    /*
     * Call before_shmem_exit callbacks.
     *
index f3f0add1d6d29cba7969ee0ce85e1fc4e5c63939..75a6dde32b3e38592c2bae259a51fef62624356f 100644 (file)
@@ -22,6 +22,7 @@
 #include "catalog/pg_type.h"
 #include "commands/portalcmds.h"
 #include "miscadmin.h"
+#include "storage/ipc.h"
 #include "utils/builtins.h"
 #include "utils/memutils.h"
 #include "utils/snapmgr.h"
@@ -757,6 +758,13 @@ AtAbort_Portals(void)
    {
        Portal      portal = hentry->portal;
 
+       /*
+        * When elog(FATAL) is progress, we need to set the active portal to
+        * failed, so that PortalCleanup() doesn't run the executor shutdown.
+        */
+       if (portal->status == PORTAL_ACTIVE && shmem_exit_inprogress)
+           MarkPortalFailed(portal);
+
        /*
         * Do nothing else to cursors held over from a previous transaction.
         */
index e934a83a1c9860a843d8a347bd32a3507fa45eaf..6a05a89349cd72377577df08054b719228eadb99 100644 (file)
@@ -63,6 +63,7 @@ typedef void (*shmem_startup_hook_type) (void);
 
 /* ipc.c */
 extern PGDLLIMPORT bool proc_exit_inprogress;
+extern PGDLLIMPORT bool shmem_exit_inprogress;
 
 extern void proc_exit(int code) pg_attribute_noreturn();
 extern void shmem_exit(int code);