Обсуждение: Proposal for Prototype Implementation to Enhance C/C++ Interoperability in PostgreSQL

Поиск
Список
Период
Сортировка

Proposal for Prototype Implementation to Enhance C/C++ Interoperability in PostgreSQL

От
"盏一"
Дата:
Hi


I am writing to propose a prototype implementation that can greatly enhance the C/C++ interoperability in PostgreSQL. The implementation involves converting PG longjmp to [force unwind](https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#base-throw), which triggers the destruction of local variables on the stack. Additionally, it converts throw statements that are not associated with catch to PG longjmp, thereby avoiding the call to terminate.


The proposed implementation can significantly improve the interoperability between C and C++ code in PostgreSQL. It allows for seamless integration of C++ code with PostgreSQL, without the need for complex workarounds or modifications to the existing codebase.


I have submitted the implementation on [GitHub](https://github.com/postgres/postgres/commit/1a9a2790430f256d9d0cc371249e43769d93eb8e#diff-6b6034caa00ddf38f641cbd10d5a5d1bb7135f8b23c5a879e9703bd11bd8240f). I would appreciate it if you could review the implementation and provide feedback.


Thank you for your time and consideration.


Best regards,

盏一----------


"=?utf-8?B?55uP5LiA?=" <w@hidva.com> writes:
> The proposed implementation can significantly improve the interoperability between C and C++ code in PostgreSQL. It
allowsfor seamless integration of C++ code with PostgreSQL, without the need for complex workarounds or modifications
tothe existing codebase. 

That'd be nice to have, certainly ...

> I have submitted the implementation
on [GitHub](https://github.com/postgres/postgres/commit/1a9a2790430f256d9d0cc371249e43769d93eb8e#diff-6b6034caa00ddf38f641cbd10d5a5d1bb7135f8b23c5a879e9703bd11bd8240f).
Iwould appreciate it if you could review the implementation and provide feedback. 

... but I think this patch has no hope of being adequately portable.
It seems extremely specific to one particular C++ implementation
(unless you can show that every single thing you've used here is
in the C++ standard), and then for good measure you've thrown in
a new dependency on pthreads.  On top of that, doesn't this
require us to move our minimum language requirement to C++-something?
We just barely got done deciding C99 was okay to use.

            regards, tom lane



> It seems extremely specific to one particular C++ implementation

To perform a force unwind during longjmp, the _Unwind_ForcedUnwind function is used. This function is defined in the [Itanium C++ ABI Standard](https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#base-throw), which is followed by all C++ implementations. Additionally, the glibc [nptl/unwind.c](https://elixir.bootlin.com/glibc/latest/source/nptl/unwind.c#L130) file shows that on all platforms, pthread_exit is also implemented using _Unwind_ForcedUnwind.

Furthermore, the Itanium C++ ABI specification also defines _Unwind_RaiseException as the entry point for all C++ exceptions thrown.

> you've thrown in a new dependency on pthreads

The reason for the dependence on pthread is due to the overloading of _Unwind_RaiseException, which serves as the entry point for all C++ throwing exceptions. Some third-party C++ libraries may create threads internally and throw exceptions.

Overloading _Unwind_RaiseException is done to convert uncaught exceptions into elog(ERROR). If we require that all exceptions must be caught, we can remove the overloading of _Unwind_RaiseException and all pthread dependencies.

The overloading of _Unwind_RaiseException is just a fallback measure to prevent uncaught exceptions from terminating the process. In our code, this path is rarely taken, and once we encounter an exception that is not caught, we will fix the code to catch the exception.

> doesn't this require us to move our minimum language requirement to C++-something?

No, all code has no dependency on C++.
 
------------------ Original ------------------
Date:  Sun, May 7, 2023 11:35 PM
To:  "盏一"<w@hidva.com>;
Cc:  "pgsql-hackers"<pgsql-hackers@postgresql.org>;
Subject:  Re: Proposal for Prototype Implementation to Enhance C/C++ Interoperability in PostgreSQL
 
"盏一" <w@hidva.com> writes:
> The proposed implementation can significantly improve the interoperability between C and C++ code in PostgreSQL. It allows for seamless integration of C++ code with PostgreSQL, without the need for complex workarounds or modifications to the existing codebase.

That'd be nice to have, certainly ...

> I have submitted the implementation on&nbsp;[GitHub](https://github.com/postgres/postgres/commit/1a9a2790430f256d9d0cc371249e43769d93eb8e#diff-6b6034caa00ddf38f641cbd10d5a5d1bb7135f8b23c5a879e9703bd11bd8240f). I would appreciate it if you could review the implementation and provide feedback.

... but I think this patch has no hope of being adequately portable.
It seems extremely specific to one particular C++ implementation
(unless you can show that every single thing you've used here is
in the C++ standard), and then for good measure you've thrown in
a new dependency on pthreads.  On top of that, doesn't this
require us to move our minimum language requirement to C++-something?
We just barely got done deciding C99 was okay to use.

regards, tom lane
(Sorry, there was a problem with the format of the previous email content. I will send it in plain text format this
time

> It seems extremely specific to one particular C++ implementation

To perform a force unwind during longjmp, the _Unwind_ForcedUnwind function is used. This function is defined in the
[ItaniumC++ ABI Standard](https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#base-throw), which is followed by all
C++implementations. Additionally, the glibc
[nptl/unwind.c](https://elixir.bootlin.com/glibc/latest/source/nptl/unwind.c#L130)file shows that on all platforms,
pthread_exitis also implemented using _Unwind_ForcedUnwind.
 

Furthermore, the Itanium C++ ABI specification also defines _Unwind_RaiseException as the entry point for all C++
exceptionsthrown.
 

> you've thrown in a new dependency on pthreads

The reason for the dependence on pthread is due to the overloading of _Unwind_RaiseException, which serves as the entry
pointfor all C++ throwing exceptions. Some third-party C++ libraries may create threads internally and throw
exceptions.

Overloading _Unwind_RaiseException is done to convert uncaught exceptions into elog(ERROR). If we require that all
exceptionsmust be caught, we can remove the overloading of _Unwind_RaiseException and all pthread dependencies.
 

The overloading of _Unwind_RaiseException is just a fallback measure to prevent uncaught exceptions from terminating
theprocess. In our code, this path is rarely taken, and once we encounter an exception that is not caught, we will fix
thecode to catch the exception.
 

> doesn't this require us to move our minimum language requirement to C++-something?

No, all code has no dependency on C++.

regards, 盏一

Re: Proposal for Prototype Implementation to Enhance C/C++ Interoperability in PostgreSQL

От
Peter Eisentraut
Дата:
On 08.05.23 04:38, 盏一 wrote:
>  > It seems extremely specific to one particular C++ implementation
> 
> To perform a force unwind during longjmp, the _Unwind_ForcedUnwind 
> function is used. This function is defined in the [Itanium C++ ABI 
> Standard](https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#base-throw), which is followed by all C++
implementations.Additionally, the glibc
[nptl/unwind.c](https://elixir.bootlin.com/glibc/latest/source/nptl/unwind.c#L130)file shows that on all platforms,
pthread_exitis also implemented using _Unwind_ForcedUnwind.
 
> 
> Furthermore, the Itanium C++ ABI specification also defines 
> _Unwind_RaiseException as the entry point for all C++ exceptions thrown.

I ran your patch through Cirrus CI, and it passed on Linux but failed on 
FreeBSD, macOS, and Windows.  You should fix that if you want to 
alleviate the concerns about the portability of this approach.




I apologize for my previous hasty conclusion. I have conducted further testing on different platforms and would like to
sharemy findings.
 

> FreeBSD

Based on my tests, it appears that FreeBSD follows the Itanium C++ ABI specification. The previous test failed because
theC++ compiler was not used when linking libpgsjlj.so.
 

> macOS, M1

My tests show that macOS M1 roughly follows the Itanium C++ ABI specification, with only slight differences, such as
theparameters accepted by the _Unwind_Stop_Fn function.
 

> macOS, x86

I don't have the resources to do the testing, but from a code perspective, it appears that macOS x86 follows the
ItaniumC++ ABI specification.
 

> Windows

It seems that Windows does not follow the Itanium C++ ABI specification at all. If we compile the program using the
`/EHsc`option, longjmp will also trigger forced unwinding. However, unlike the Itanium C++ ABI, the forced unwinding
triggeredhere cannot be captured by a C++ catch statement.