 doc/src/sgml/custom-scan.sgml          | 44 ++++++++++++++++++++++++++++++++++
 doc/src/sgml/fdwhandler.sgml           | 11 +++++++++
 src/backend/executor/execProcnode.c    |  6 +++++
 src/backend/executor/nodeCustom.c      |  9 +++++++
 src/backend/executor/nodeForeignscan.c | 16 +++++++++++++
 src/include/executor/nodeCustom.h      |  1 +
 src/include/executor/nodeForeignscan.h |  1 +
 src/include/foreign/fdwapi.h           |  2 ++
 src/include/nodes/extensible.h         |  1 +
 9 files changed, 91 insertions(+)

diff --git a/doc/src/sgml/custom-scan.sgml b/doc/src/sgml/custom-scan.sgml
index 1ca9247..ef8a57c 100644
--- a/doc/src/sgml/custom-scan.sgml
+++ b/doc/src/sgml/custom-scan.sgml
@@ -240,6 +240,40 @@ typedef struct CustomScanState
    structure embedding the above as its first member.
   </para>
 
+  <para>
+   The simplest execution life-cycle of <structname>CustomScanState</> has
+   three basic steps. First, executor calls <function>BeginCustomScan</> with
+   <structname>CustomScanState</> object allocated by
+   by <function>CreateCustomScanState</>. Next, <function>ExecCustomScan</>
+   shall be called repeatedly until it returns valid tuples.
+   Last, <function>EndCustomScan</> shall be called. 
+  </para>
+
+  <para>
+   According to the type of upper plan node, it may call
+   <function>ReScanCustomScan</>, <function>MarkPosCustomScan</> or
+   <function>RestrPosCustomScan</> during execution on demand.
+  </para>
+
+  <para>
+   If custom-scan works under CPU parallel, some more interaction with
+   executor are required.
+   Prior to launch of background workers, <function>EstimateDSMCustomScan</>
+   is called next to creation of the <structname>CustomScanState</>, to
+   inform amount of the DSM segment required by the custom-scan node.
+   Then, <function>InitializeDSMCustomScan</> is called to initialize the
+   DSM area which is allocated for the custom-scan node.
+   Once execution gets started, <literal>Gather</> node kicks background
+   worker processes, then <function>InitializeWorkerCustomScan</> is called
+   on the worker process's context, to initialize extra stuff based on the
+   DSM contents.
+   After the execution of worker process, <literal>Gather</> synchronizes
+   its completion, then <function>ShutdownCustomScan</> is called, but
+   prior to release of the DSM segment. So, if custom-scan node wants to
+   return its own extra information using DSM, it has to be retrieved at
+   this point.
+  </para>
+
   <sect2 id="custom-scan-execution-callbacks">
    <title>Custom Scan Execution Callbacks</title>
 
@@ -340,6 +374,16 @@ void (*InitializeWorkerCustomScan) (CustomScanState *node,
 
    <para>
 <programlisting>
+void (*ShutdownCustomScan) (CustomScanState *node);
+</programlisting>
+    Stops asynchronous resource consumption, retrieves contents on the
+    DSM segment, or release any resources still held.
+    This callback is optional, and makes sense only if this custom path
+    works under parallel execution.
+   </para>
+
+   <para>
+<programlisting>
 void (*ExplainCustomScan) (CustomScanState *node,
                            List *ancestors,
                            ExplainState *es);
diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml
index 0c1db07..b51a2ac 100644
--- a/doc/src/sgml/fdwhandler.sgml
+++ b/doc/src/sgml/fdwhandler.sgml
@@ -1254,6 +1254,17 @@ InitializeWorkerForeignScan(ForeignScanState *node, shm_toc *toc,
     This callback is optional, and needs only be supplied if this
     custom path supports parallel execution.
    </para>
+
+   <para>
+<programlisting>
+void
+ShutdownForeignScan(ForeignScanState *node);
+</programlisting>
+    Stops asynchronous resource consumption, retrieves contents on the
+    DSM segment, or release any resources still held.
+    This callback is optional, and makes sense only if this custom path
+    works under parallel execution.
+   </para>
    </sect2>
 
    </sect1>
diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c
index 5ccc2e8..ef6f35a 100644
--- a/src/backend/executor/execProcnode.c
+++ b/src/backend/executor/execProcnode.c
@@ -822,6 +822,12 @@ ExecShutdownNode(PlanState *node)
 		case T_GatherState:
 			ExecShutdownGather((GatherState *) node);
 			break;
+		case T_ForeignScanState:
+			ExecShutdownForeignScan((ForeignScanState *) node);
+			break;
+		case T_CustomScanState:
+			ExecShutdownCustomScan((CustomScanState *) node);
+			break;
 		default:
 			break;
 	}
diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c
index 16343a5..d464748 100644
--- a/src/backend/executor/nodeCustom.c
+++ b/src/backend/executor/nodeCustom.c
@@ -202,3 +202,12 @@ ExecCustomScanInitializeWorker(CustomScanState *node, shm_toc *toc)
 		methods->InitializeWorkerCustomScan(node, toc, coordinate);
 	}
 }
+
+void
+ExecShutdownCustomScan(CustomScanState *node)
+{
+	const CustomExecMethods *methods = node->methods;
+
+	if (methods->ShutdownCustomScan)
+		methods->ShutdownCustomScan(node);
+}
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index 86a77e3..3b6d139 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -353,3 +353,19 @@ ExecForeignScanInitializeWorker(ForeignScanState *node, shm_toc *toc)
 		fdwroutine->InitializeWorkerForeignScan(node, toc, coordinate);
 	}
 }
+
+/* ----------------------------------------------------------------
+ *		ExecShutdownForeignScan
+ *
+ *		Gives FDW chance to stop asynchronous resource consumption
+ *		and release any resources still held.
+ * ----------------------------------------------------------------
+ */
+void
+ExecShutdownForeignScan(ForeignScanState *node)
+{
+	FdwRoutine *fdwroutine = node->fdwroutine;
+
+	if (fdwroutine->ShutdownForeignScan)
+		fdwroutine->ShutdownForeignScan(node);
+}
diff --git a/src/include/executor/nodeCustom.h b/src/include/executor/nodeCustom.h
index 19d5d04..c2f2ca1 100644
--- a/src/include/executor/nodeCustom.h
+++ b/src/include/executor/nodeCustom.h
@@ -37,5 +37,6 @@ extern void ExecCustomScanInitializeDSM(CustomScanState *node,
 							ParallelContext *pcxt);
 extern void ExecCustomScanInitializeWorker(CustomScanState *node,
 							   shm_toc *toc);
+extern void ExecShutdownCustomScan(CustomScanState *node);
 
 #endif   /* NODECUSTOM_H */
diff --git a/src/include/executor/nodeForeignscan.h b/src/include/executor/nodeForeignscan.h
index f0e942a..1b167b8 100644
--- a/src/include/executor/nodeForeignscan.h
+++ b/src/include/executor/nodeForeignscan.h
@@ -28,5 +28,6 @@ extern void ExecForeignScanInitializeDSM(ForeignScanState *node,
 							 ParallelContext *pcxt);
 extern void ExecForeignScanInitializeWorker(ForeignScanState *node,
 								shm_toc *toc);
+extern void ExecShutdownForeignScan(ForeignScanState *node);
 
 #endif   /* NODEFOREIGNSCAN_H */
diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h
index 523d415..6ca44f7 100644
--- a/src/include/foreign/fdwapi.h
+++ b/src/include/foreign/fdwapi.h
@@ -151,6 +151,7 @@ typedef void (*InitializeDSMForeignScan_function) (ForeignScanState *node,
 typedef void (*InitializeWorkerForeignScan_function) (ForeignScanState *node,
 																shm_toc *toc,
 														   void *coordinate);
+typedef void (*ShutdownForeignScan_function) (ForeignScanState *node);
 typedef bool (*IsForeignScanParallelSafe_function) (PlannerInfo *root,
 															 RelOptInfo *rel,
 														 RangeTblEntry *rte);
@@ -224,6 +225,7 @@ typedef struct FdwRoutine
 	EstimateDSMForeignScan_function EstimateDSMForeignScan;
 	InitializeDSMForeignScan_function InitializeDSMForeignScan;
 	InitializeWorkerForeignScan_function InitializeWorkerForeignScan;
+	ShutdownForeignScan_function ShutdownForeignScan;
 } FdwRoutine;
 
 
diff --git a/src/include/nodes/extensible.h b/src/include/nodes/extensible.h
index 7e860b0..0b02cc1 100644
--- a/src/include/nodes/extensible.h
+++ b/src/include/nodes/extensible.h
@@ -139,6 +139,7 @@ typedef struct CustomExecMethods
 	void		(*InitializeWorkerCustomScan) (CustomScanState *node,
 														   shm_toc *toc,
 														   void *coordinate);
+	void		(*ShutdownCustomScan) (CustomScanState *node);
 
 	/* Optional: print additional information in EXPLAIN */
 	void		(*ExplainCustomScan) (CustomScanState *node,
