Re: Mostly Harmless: c++exception - patch 4 of 4 - Mailing list pgsql-hackers

From Kurt Harriman
Subject Re: Mostly Harmless: c++exception - patch 4 of 4
Date
Msg-id 4938F252.7090706@acm.org
Whole thread Raw
In response to Mostly Harmless: Welcoming our C++ friends  (Kurt Harriman <harriman@acm.org>)
List pgsql-hackers
(Re-sending just the fourth of four patches: c++exception)

These patches are based on CVS head in which the latest commit was
  user:        petere
  date:        Thu Dec 04 17:51:28 2008 +0000
  summary:     Default values for function arguments

4. c++exception

     When C code calls C++ code, all C++ exceptions need to be caught
     and fully contained within the C++ code.  Exceptions should never
     be thrown outward across the C/C++ frontier.

     If an exception is not caught within C++ code, and the search for
     a matching 'catch' bumps into a C stack frame, the result may be
     platform dependent.  On my platform (Linux/GCC), if this happens
     in the postgres backend, the process terminates silently as if
     abort() had been called.

     With this patch, if --enable-cplusplus is configured,
     PostgresMain defines a handler to intercept any uncaught C++
     exception and convert it to a conventional PostgreSQL error of
     FATAL severity.  This allows the backend to clean up and report
     the error before terminating.

diff -r 9b2c774a6b05 src/backend/tcop/Makefile
--- a/src/backend/tcop/Makefile
+++ b/src/backend/tcop/Makefile
@@ -14,6 +14,11 @@

 OBJS= dest.o fastpath.o postgres.o pquery.o utility.o

+# Designate modules to be compiled as C++ when 'configure --enable-cplusplus'
+ifeq ($(enable_cplusplus),yes)
+CXXOBJS = postgres.o
+endif
+
 ifneq (,$(filter $(PORTNAME),cygwin win32))
 override CPPFLAGS += -DWIN32_STACK_RLIMIT=$(WIN32_STACK_RLIMIT)
 endif
diff -r 9b2c774a6b05 src/backend/tcop/postgres.c
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -33,6 +33,17 @@
 #endif
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
+#endif
+
+#ifdef ENABLE_CPLUSPLUS
+#ifndef __cplusplus
+#error --enable-cplusplus configure option specified; this file should be compiled as C++
+#endif
+#include <exception>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
 #endif

 #ifndef HAVE_GETRUSAGE
@@ -163,6 +174,11 @@
 #endif   /* TCOP_DONTUSENEWLINE */


+#ifdef __cplusplus
+}                               /* extern "C" */
+#endif
+
+
 /* ----------------------------------------------------------------
  *        decls for routines only used in this file
  * ----------------------------------------------------------------
@@ -1212,7 +1228,7 @@
         if (log_parser_stats)
             ResetUsage();

-        query = parse_analyze_varparams(copyObject(raw_parse_tree),
+        query = parse_analyze_varparams((Node *)copyObject(raw_parse_tree),
                                         query_string,
                                         ¶mTypes,
                                         &numParams);
@@ -1679,7 +1695,7 @@
          * we have to make a copy of the parse trees.  FIXME someday.
          */
         oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
-        query_list = copyObject(cplan->stmt_list);
+        query_list = (List *)copyObject(cplan->stmt_list);
         plan_list = pg_plan_queries(query_list, 0, params, true);
         MemoryContextSwitchTo(oldContext);

@@ -2791,6 +2807,29 @@

     return NULL;
 }
+
+
+#ifdef ENABLE_CPLUSPLUS
+/*
+ * PostgresMainUncaught
+ *      Called when C++ code throws an exception which is not caught.
+ *
+ * NB: On some platforms when C++ code calls C code, and the C code calls
+ * a deeper layer of C++ code, the outer C++ code can't catch exceptions
+ * thrown by the inner C++ code.  The search for a matching 'catch' is
+ * abandoned upon encountering an intervening C stack frame, and the
+ * exception is considered uncaught.
+ */
+static void
+PostgresMainUncaught()
+{
+    /* Context callbacks might not work right if call stack has been unwound */
+    error_context_stack = NULL;
+
+    elog(FATAL, "Unexpected internal error: Unhandled C++ exception");
+    abort();                                /* not reached */
+}
+#endif  /* ENABLE_CPLUSPLUS */


 /* ----------------------------------------------------------------
@@ -2850,6 +2889,11 @@
     /* Set up reference point for stack depth checking */
     stack_base_ptr = &stack_base;

+#ifdef ENABLE_CPLUSPLUS
+    /* Any unhandled C++ exception is to be treated as a FATAL error. */
+    std::set_terminate(PostgresMainUncaught);
+#endif
+
     /* Compute paths, if we didn't inherit them from postmaster */
     if (my_exec_path[0] == '\0')
     {
@@ -3108,10 +3152,10 @@
             char       *name;
             char       *value;

-            name = lfirst(gucopts);
+            name = (char *)lfirst(gucopts);
             gucopts = lnext(gucopts);

-            value = lfirst(gucopts);
+            value = (char *)lfirst(gucopts);
             gucopts = lnext(gucopts);

             if (IsSuperuserConfigOption(name))

pgsql-hackers by date:

Previous
From: Kurt Harriman
Date:
Subject: Re: Mostly Harmless: c++configure - patch 3 of 4
Next
From: Greg Smith
Date:
Subject: Re: Mostly Harmless: Welcoming our C++ friends