Re: server-side extension in c++ - Mailing list pgsql-general
From | Peter Geoghegan |
---|---|
Subject | Re: server-side extension in c++ |
Date | |
Msg-id | AANLkTinnqthHfIbAXwcvnanZxNYAas8M0ZdKNGBx9W2l@mail.gmail.com Whole thread Raw |
In response to | Re: server-side extension in c++ (Craig Ringer <craig@postnewspapers.com.au>) |
Responses |
Re: server-side extension in c++
|
List | pgsql-general |
> 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. Right, but I don't think that this differs from the general C++ case. Allowing exceptions to propagate across module boundaries was always a bad idea, as was managing memory across module boundaries. Aside from being very messy, they had to have exactly compatible runtimes and so on. > 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(). That's the pre-standard behaviour of operator new(), and operator new() continues to behave that way on some platforms, typically embedded systems. > 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. > Seems reasonable, and not overly difficult. > > 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. Really? That seems like an *incredibly* arduous requirement. Intuitively, I find it difficult to believe. After all, even though using longjmp in C++ code is a fast track to undefined behaviour, I would have imagined that doing so in an isolated C module with a well defined interface, called from C++ would be safe. I would have imagined that ultimately, the call to the Pg C function must return, and therefore cannot affect stack unwinding within the C++ part of the program. To invoke a reductio ad absurdum argument, if this were the case, calling C functions from C++ would be widely considered a dangerous thing to do, which it is not. After all, setjmp()/longjmp() are part of the C standard library...in general, it's difficult to know whether or not a third party module may use them. Have you ever seen a C library marked as C++ safe or C++ unsafe? No, me neither. Perhaps I'm missing something though...does the error handling portion of the pg code potentially need a hook into the C++ code, from where the longjmp() must be performed? I don't know what you mean by "a call chain by value". The bottom line is that *I think* you're fine as long as you don't do setjmp()/longjmp() from within C++. You may even be okay if you just do setjmp() from within C++. The longjmp() will hopefully only affect stack unwinding before we get down to the C++ part of the stack, where that matters. -- Regards, Peter Geoghegan
pgsql-general by date: