Re: server-side extension in c++

From: David Fetter <david(at)fetter(dot)org>
To: Craig Ringer <craig(at)postnewspapers(dot)com(dot)au>
Cc: Bruce Momjian <bruce(at)momjian(dot)us>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Igor <igor(at)carcass(dot)ath(dot)cx>, pgsql-general(at)postgresql(dot)org
Subject: Re: server-side extension in c++
Date: 2010-06-02 13:57:10
Message-ID: 20100602135710.GC6953@fetter.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

On Wed, Jun 02, 2010 at 10:11:37AM +0800, Craig Ringer wrote:
> On 02/06/10 09:23, Bruce Momjian wrote:
> > Tom Lane wrote:
> >> Craig Ringer <craig(at)postnewspapers(dot)com(dot)au> writes:
> >>> On 01/06/10 11:05, Tom Lane wrote:
> >>>> I'd be interested to see a section like this written by someone who'd
> >>>> actually done a nontrivial C++ extension and lived to tell the tale.
> >>
> >>> I can't speak up there - my own C++/Pg backend stuff has been fairly
> >>> trivial, and has been where I can maintain a fairly clean separation of
> >>> the C++-exposed and the Pg-backend-exposed parts. I was able to keep
> >>> things separate enough that my C++ compilation units didn't include the
> >>> Pg backend headers; they just exposed a pure C public interface. The Pg
> >>> backend-using compilation units were written in C, and talked to the C++
> >>> part over its exposed pure C interfaces.
> >>
> >> Yeah, if you can design your code so that C++ never has to call back
> >> into the core backend, that eliminates a large chunk of the pain.
> >> Should we be documenting design ideas like this one?
> >
> > I have incorporated the new ideas into the C++ documentation section,
> > and removed the comment block in the attached patch.
>
> If you're going to include that much, I'd still really want to warn
> people about exception/error handling too. It's important. I made brief
> mention of it before, but perhaps some more detail would help if people
> really want to do this.
>
> ( BTW, all in all, I agree with Tom Lane - the best answer is "don't".
> Sometimes you need to access functionality from C++ libraries, but
> unless that's your reason I wouldn't ever consider doing it. )
>
> Here's a rough outline of the rules I follow when mixing C/C++ code,
> plus some info on the longjmp error handling related complexities added
> by Pg:
>
>
>
> Letting an exception thrown from C++ code cross into C code will be
> EXTREMELY ugly. The C++-to-C boundaries *must* have unconditional catch
> blocks to convert thrown exceptions into appropriate error codes, even
> if the C++ code in question never knowingly throws an exception. C++ may
> throw std::bad_alloc on failure of operator new(), among other things,
> so the user must _always_ have an unconditional catch. Letting an
> exception propagate out to the C-based Pg backend is rather likely to
> result in a backend crash.
>
> If the C++ libraries you are using will put up with it, compile your C++
> code with -fno-exceptions to make your life much, much easier, as you
> can avoid worrying about this entirely. OTOH, you must then check for
> NULL return from operator new().
>
> If you can't do that: My usual rule is that any "extern C" function
> *must* have an unconditional catch. I also require that any function
> that may be passed as a function pointer to C code must be "extern C"
> and thus must obey the previous rule, so that covers function pointers
> and dlopen()ed access to functions.
>
>
>
>
> Similarly, calling Pg code that may use Pg's error handling from within
> C++ is unsafe. It should be OK if you know for absolute certain that the
> C++ call tree in question only has plain-old-data (POD) structs and
> simple variables on the stack, but even then it requires caution. C++
> code that uses Pg calls can't do anything it couldn't do if you were
> using 'goto' and labels in each involved function, but additionally has
> to worry about returning and passing non-POD objects between functions
> in a call chain by value, as a longjmp may result in dtors not being
> properly called.
>
> The best way to get around this issue is not to call into the Pg backend
> from C++ code at all, instead encapsulating your C++ functionality into
> cleanly separated modules with pure C interfaces. If you don't #include
> any Pg backend headers into any compilation units compiled with the C++
> compiler, that should do the trick.
>
> If you must mix Pg calls and C++, restrict your C++ objects to the heap
> (ie use pointers to them, managed with new and delete) and limit your
> stack to POD variables (simple structs and built-in types). Note that
> this means you can't use std::auto_ptr, std::tr1:shared_ptr, RAII lock
> management, etc in C++ code that may call into the Pg backend.

Is PostGIS following these guidelines?

Cheers,
David.
--
David Fetter <david(at)fetter(dot)org> http://fetter.org/
Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter
Skype: davidfetter XMPP: david(dot)fetter(at)gmail(dot)com
iCal: webcal://www.tripit.com/feed/ical/people/david74/tripit.ics

Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Joshua Tolley 2010-06-02 13:57:37 Re: Statement Pooling
Previous Message David Fetter 2010-06-02 13:28:14 Re: Is it possible to make the order of output the same as the order of input parameters?