Skip to content

Commit fc1c18f

Browse files
committed
switch to C-unwind
1 parent abd4661 commit fc1c18f

File tree

25 files changed

+109
-107
lines changed

25 files changed

+109
-107
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
+ Safe access to Postgres' `MemoryContext` system via `pgrx::PgMemoryContexts`
6464
+ Executor/planner/transaction/subtransaction hooks
6565
+ Safely use Postgres-provided pointers with `pgrx::PgBox<T>` (akin to `alloc::boxed::Box<T>`)
66-
+ `#[pg_guard]` proc-macro for guarding `extern "C"` Rust functions that need to be passed into Postgres
66+
+ `#[pg_guard]` proc-macro for guarding `extern "C-unwind"` Rust functions that need to be passed into Postgres
6767
+ Access Postgres' logging system through `eprintln!`-like macros
6868
+ Direct `unsafe` access to large parts of Postgres internals via the `pgrx::pg_sys` module
6969
+ New features added regularly!

cargo-pgrx/src/templates/bgworker_lib_rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ this background worker
2121

2222
#[allow(non_snake_case)]
2323
#[pg_guard]
24-
pub extern "C" fn _PG_init() {{
24+
pub extern "C-unwind" fn _PG_init() {{
2525
BackgroundWorkerBuilder::new("{name}")
2626
.set_function("background_worker_main")
2727
.set_library("{name}")
@@ -32,7 +32,7 @@ pub extern "C" fn _PG_init() {{
3232

3333
#[pg_guard]
3434
#[no_mangle]
35-
pub extern "C" fn background_worker_main(arg: pg_sys::Datum) {{
35+
pub extern "C-unwind" fn background_worker_main(arg: pg_sys::Datum) {{
3636
let arg = unsafe {{ i32::from_datum(arg, false) }};
3737

3838
// these are the signals we want to receive. If we don't attach the SIGTERM handler, then

pgrx-bindgen/src/build.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,7 @@ fn run_bindgen(
829829
.wrap_static_fns(enable_cshim)
830830
.wrap_static_fns_path(out_path.join("pgrx-cshim-static"))
831831
.wrap_static_fns_suffix("__pgrx_cshim")
832+
.override_abi(bindgen::Abi::CUnwind, ".*")
832833
.generate()
833834
.wrap_err_with(|| format!("Unable to generate bindings for pg{major_version}"))?;
834835
let mut binding_str = bindings.to_string();
@@ -866,7 +867,7 @@ fn add_blocklists(bind: bindgen::Builder) -> bindgen::Builder {
866867
.blocklist_var("CONFIGURE_ARGS") // configuration during build is hopefully irrelevant
867868
.blocklist_var("_*(?:HAVE|have)_.*") // header tracking metadata
868869
.blocklist_var("_[A-Z_]+_H") // more header metadata
869-
// It's used by explict `extern "C"`
870+
// It's used by explict `extern "C-unwind"`
870871
.blocklist_function("pg_re_throw")
871872
.blocklist_function("err(start|code|msg|detail|context_msg|hint|finish)")
872873
// These functions are already ported in Rust

pgrx-examples/bad_ideas/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ fn random_abort() {
114114
}
115115

116116
#[pg_guard]
117-
pub unsafe extern "C" fn _PG_init() {
117+
pub unsafe extern "C-unwind" fn _PG_init() {
118118
#[pg_guard]
119-
extern "C" fn random_abort_callback(
119+
extern "C-unwind" fn random_abort_callback(
120120
event: pg_sys::XactEvent::Type,
121121
_arg: *mut std::os::raw::c_void,
122122
) {

pgrx-examples/bgworker/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use std::time::Duration;
2929
::pgrx::pg_module_magic!();
3030

3131
#[pg_guard]
32-
pub extern "C" fn _PG_init() {
32+
pub extern "C-unwind" fn _PG_init() {
3333
BackgroundWorkerBuilder::new("Background Worker Example")
3434
.set_function("background_worker_main")
3535
.set_library("bgworker")
@@ -40,7 +40,7 @@ pub extern "C" fn _PG_init() {
4040

4141
#[pg_guard]
4242
#[no_mangle]
43-
pub extern "C" fn background_worker_main(arg: pg_sys::Datum) {
43+
pub extern "C-unwind" fn background_worker_main(arg: pg_sys::Datum) {
4444
let arg = unsafe { i32::from_polymorphic_datum(arg, false, pg_sys::INT4OID) };
4545

4646
// these are the signals we want to receive. If we don't attach the SIGTERM handler, then

pgrx-examples/shmem/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ static PRIMITIVE: PgLwLock<i32> = PgLwLock::new(c"shmem_primtive");
3737
static ATOMIC: PgAtomic<std::sync::atomic::AtomicBool> = PgAtomic::new(c"shmem_atomic");
3838

3939
#[pg_guard]
40-
pub extern "C" fn _PG_init() {
40+
pub extern "C-unwind" fn _PG_init() {
4141
pg_shmem_init!(DEQUE);
4242
pg_shmem_init!(VEC);
4343
pg_shmem_init!(HASH);

pgrx-examples/wal_decoder/src/lib.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ impl Serialize for Tuple {
191191
#[allow(non_snake_case)]
192192
#[no_mangle]
193193
#[pg_guard]
194-
pub unsafe extern "C" fn _PG_output_plugin_init(cb_ptr: *mut pg_sys::OutputPluginCallbacks) {
194+
pub unsafe extern "C-unwind" fn _PG_output_plugin_init(cb_ptr: *mut pg_sys::OutputPluginCallbacks) {
195195
let mut callbacks = unsafe { PgBox::from_pg(cb_ptr) };
196196
callbacks.startup_cb = Some(pg_decode_startup);
197197
callbacks.begin_cb = Some(pg_decode_begin_txn);
@@ -209,7 +209,7 @@ pub unsafe extern "C" fn _PG_output_plugin_init(cb_ptr: *mut pg_sys::OutputPlugi
209209
//
210210

211211
#[pg_guard]
212-
unsafe extern "C" fn pg_decode_startup(
212+
unsafe extern "C-unwind" fn pg_decode_startup(
213213
ctx_ptr: *mut pg_sys::LogicalDecodingContext,
214214
options_ptr: *mut pg_sys::OutputPluginOptions,
215215
_is_init: bool,
@@ -229,7 +229,7 @@ unsafe extern "C" fn pg_decode_startup(
229229
}
230230

231231
#[pg_guard]
232-
unsafe extern "C" fn pg_decode_begin_txn(
232+
unsafe extern "C-unwind" fn pg_decode_begin_txn(
233233
ctx_ptr: *mut pg_sys::LogicalDecodingContext,
234234
_txn_ptr: *mut pg_sys::ReorderBufferTXN,
235235
) {
@@ -240,7 +240,7 @@ unsafe extern "C" fn pg_decode_begin_txn(
240240
}
241241

242242
#[pg_guard]
243-
unsafe extern "C" fn pg_decode_commit_txn(
243+
unsafe extern "C-unwind" fn pg_decode_commit_txn(
244244
ctx_ptr: *mut pg_sys::LogicalDecodingContext,
245245
txn_ptr: *mut pg_sys::ReorderBufferTXN,
246246
_commit_lsn: pg_sys::XLogRecPtr,
@@ -252,7 +252,7 @@ unsafe extern "C" fn pg_decode_commit_txn(
252252
}
253253

254254
#[pg_guard]
255-
unsafe extern "C" fn pg_decode_change(
255+
unsafe extern "C-unwind" fn pg_decode_change(
256256
ctx_ptr: *mut pg_sys::LogicalDecodingContext,
257257
_txn_ptr: *mut pg_sys::ReorderBufferTXN,
258258
relation: pg_sys::Relation,
@@ -269,7 +269,7 @@ unsafe extern "C" fn pg_decode_change(
269269
}
270270

271271
#[pg_guard]
272-
unsafe extern "C" fn pg_decode_shutdown(ctx_ptr: *mut pg_sys::LogicalDecodingContext) {
272+
unsafe extern "C-unwind" fn pg_decode_shutdown(ctx_ptr: *mut pg_sys::LogicalDecodingContext) {
273273
let layout = Layout::new::<DecodingState>();
274274
let ctx = unsafe { PgBox::from_pg(ctx_ptr) };
275275
unsafe { dealloc(ctx.output_plugin_private as *mut u8, layout) };

pgrx-macros/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,23 @@ use sql_gen::{
2727
mod operators;
2828
mod rewriter;
2929

30-
/// Declare a function as `#[pg_guard]` to indicate that it is called from a Postgres `extern "C"`
30+
/// Declare a function as `#[pg_guard]` to indicate that it is called from a Postgres `extern "C-unwind"`
3131
/// function so that Rust `panic!()`s (and Postgres `elog(ERROR)`s) will be properly handled by `pgrx`
3232
#[proc_macro_attribute]
3333
pub fn pg_guard(_attr: TokenStream, item: TokenStream) -> TokenStream {
3434
// get a usable token stream
3535
let ast = parse_macro_input!(item as syn::Item);
3636

3737
let res = match ast {
38-
// this is for processing the members of extern "C" { } blocks
38+
// this is for processing the members of extern "C-unwind" { } blocks
3939
// functions inside the block get wrapped as public, top-level unsafe functions that are not "extern"
4040
Item::ForeignMod(block) => Ok(rewriter::extern_block(block)),
4141

4242
// process top-level functions
4343
Item::Fn(func) => rewriter::item_fn_without_rewrite(func),
4444
unknown => Err(syn::Error::new(
4545
unknown.span(),
46-
"#[pg_guard] can only be applied to extern \"C\" blocks and top-level functions",
46+
"#[pg_guard] can only be applied to extern \"C-unwind\" blocks and top-level functions",
4747
)),
4848
};
4949
res.unwrap_or_else(|e| e.into_compile_error()).into()

pgrx-pg-sys/src/cshim.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use crate as pg_sys;
55

66
#[pgrx_macros::pg_guard]
7-
extern "C" {
7+
extern "C-unwind" {
88
#[link_name = "SpinLockInit__pgrx_cshim"]
99
pub fn SpinLockInit(lock: *mut pg_sys::slock_t);
1010
#[link_name = "SpinLockAcquire__pgrx_cshim"]

pgrx-pg-sys/src/port.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ pub unsafe fn GetMemoryChunkContext(pointer: *mut std::os::raw::c_void) -> pg_sy
106106
#[cfg(any(feature = "pg16", feature = "pg17"))]
107107
{
108108
#[pgrx_macros::pg_guard]
109-
extern "C" {
109+
extern "C-unwind" {
110110
#[link_name = "GetMemoryChunkContext"]
111111
pub fn extern_fn(pointer: *mut std::os::raw::c_void) -> pg_sys::MemoryContext;
112112
}
@@ -340,19 +340,19 @@ pub unsafe fn heap_tuple_get_struct<T>(htup: super::HeapTuple) -> *mut T {
340340
// and we route people to the old symbols they were using before on later ones.
341341
#[cfg(any(feature = "pg12", feature = "pg13", feature = "pg14", feature = "pg15"))]
342342
#[::pgrx_macros::pg_guard]
343-
extern "C" {
343+
extern "C-unwind" {
344344
pub fn planstate_tree_walker(
345345
planstate: *mut super::PlanState,
346346
walker: ::core::option::Option<
347-
unsafe extern "C" fn(*mut super::PlanState, *mut ::core::ffi::c_void) -> bool,
347+
unsafe extern "C-unwind" fn(*mut super::PlanState, *mut ::core::ffi::c_void) -> bool,
348348
>,
349349
context: *mut ::core::ffi::c_void,
350350
) -> bool;
351351

352352
pub fn query_tree_walker(
353353
query: *mut super::Query,
354354
walker: ::core::option::Option<
355-
unsafe extern "C" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
355+
unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
356356
>,
357357
context: *mut ::core::ffi::c_void,
358358
flags: ::core::ffi::c_int,
@@ -361,7 +361,7 @@ extern "C" {
361361
pub fn query_or_expression_tree_walker(
362362
node: *mut super::Node,
363363
walker: ::core::option::Option<
364-
unsafe extern "C" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
364+
unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
365365
>,
366366
context: *mut ::core::ffi::c_void,
367367
flags: ::core::ffi::c_int,
@@ -370,7 +370,7 @@ extern "C" {
370370
pub fn range_table_entry_walker(
371371
rte: *mut super::RangeTblEntry,
372372
walker: ::core::option::Option<
373-
unsafe extern "C" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
373+
unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
374374
>,
375375
context: *mut ::core::ffi::c_void,
376376
flags: ::core::ffi::c_int,
@@ -379,7 +379,7 @@ extern "C" {
379379
pub fn range_table_walker(
380380
rtable: *mut super::List,
381381
walker: ::core::option::Option<
382-
unsafe extern "C" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
382+
unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
383383
>,
384384
context: *mut ::core::ffi::c_void,
385385
flags: ::core::ffi::c_int,
@@ -388,15 +388,15 @@ extern "C" {
388388
pub fn expression_tree_walker(
389389
node: *mut super::Node,
390390
walker: ::core::option::Option<
391-
unsafe extern "C" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
391+
unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
392392
>,
393393
context: *mut ::core::ffi::c_void,
394394
) -> bool;
395395

396396
pub fn raw_expression_tree_walker(
397397
node: *mut super::Node,
398398
walker: ::core::option::Option<
399-
unsafe extern "C" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
399+
unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
400400
>,
401401
context: *mut ::core::ffi::c_void,
402402
) -> bool;
@@ -406,7 +406,7 @@ extern "C" {
406406
pub unsafe fn planstate_tree_walker(
407407
planstate: *mut super::PlanState,
408408
walker: ::core::option::Option<
409-
unsafe extern "C" fn(*mut super::PlanState, *mut ::core::ffi::c_void) -> bool,
409+
unsafe extern "C-unwind" fn(*mut super::PlanState, *mut ::core::ffi::c_void) -> bool,
410410
>,
411411
context: *mut ::core::ffi::c_void,
412412
) -> bool {
@@ -417,7 +417,7 @@ pub unsafe fn planstate_tree_walker(
417417
pub unsafe fn query_tree_walker(
418418
query: *mut super::Query,
419419
walker: ::core::option::Option<
420-
unsafe extern "C" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
420+
unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
421421
>,
422422
context: *mut ::core::ffi::c_void,
423423
flags: ::core::ffi::c_int,
@@ -429,7 +429,7 @@ pub unsafe fn query_tree_walker(
429429
pub unsafe fn query_or_expression_tree_walker(
430430
node: *mut super::Node,
431431
walker: ::core::option::Option<
432-
unsafe extern "C" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
432+
unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
433433
>,
434434
context: *mut ::core::ffi::c_void,
435435
flags: ::core::ffi::c_int,
@@ -440,7 +440,7 @@ pub unsafe fn query_or_expression_tree_walker(
440440
#[cfg(any(feature = "pg16", feature = "pg17"))]
441441
pub unsafe fn expression_tree_walker(
442442
node: *mut crate::Node,
443-
walker: Option<unsafe extern "C" fn(*mut crate::Node, *mut ::core::ffi::c_void) -> bool>,
443+
walker: Option<unsafe extern "C-unwind" fn(*mut crate::Node, *mut ::core::ffi::c_void) -> bool>,
444444
context: *mut ::core::ffi::c_void,
445445
) -> bool {
446446
crate::expression_tree_walker_impl(node, walker, context)
@@ -450,7 +450,7 @@ pub unsafe fn expression_tree_walker(
450450
pub unsafe fn range_table_entry_walker(
451451
rte: *mut super::RangeTblEntry,
452452
walker: ::core::option::Option<
453-
unsafe extern "C" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
453+
unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
454454
>,
455455
context: *mut ::core::ffi::c_void,
456456
flags: ::core::ffi::c_int,
@@ -462,7 +462,7 @@ pub unsafe fn range_table_entry_walker(
462462
pub unsafe fn range_table_walker(
463463
rtable: *mut super::List,
464464
walker: ::core::option::Option<
465-
unsafe extern "C" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
465+
unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
466466
>,
467467
context: *mut ::core::ffi::c_void,
468468
flags: ::core::ffi::c_int,
@@ -473,7 +473,7 @@ pub unsafe fn range_table_walker(
473473
#[cfg(any(feature = "pg16", feature = "pg17"))]
474474
pub unsafe fn raw_expression_tree_walker(
475475
node: *mut crate::Node,
476-
walker: Option<unsafe extern "C" fn(*mut crate::Node, *mut ::core::ffi::c_void) -> bool>,
476+
walker: Option<unsafe extern "C-unwind" fn(*mut crate::Node, *mut ::core::ffi::c_void) -> bool>,
477477
context: *mut ::core::ffi::c_void,
478478
) -> bool {
479479
crate::raw_expression_tree_walker_impl(node, walker, context)

pgrx-pg-sys/src/submodules/ffi.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,18 @@ mod cee_scape {
3030
where
3131
F: for<'a> FnOnce(&'a SigJmpBufFields) -> c_int,
3232
{
33-
extern "C" {
33+
extern "C-unwind" {
3434
fn call_closure_with_sigsetjmp(
3535
savemask: c_int,
3636
closure_env_ptr: *mut c_void,
37-
closure_code: extern "C" fn(
37+
closure_code: extern "C-unwind" fn(
3838
jbuf: *const SigJmpBufFields,
3939
env_ptr: *mut c_void,
4040
) -> c_int,
4141
) -> c_int;
4242
}
4343

44-
extern "C" fn call_from_c_to_rust<F>(
44+
extern "C-unwind" fn call_from_c_to_rust<F>(
4545
jbuf: *const SigJmpBufFields,
4646
closure_env_ptr: *mut c_void,
4747
) -> c_int
@@ -69,7 +69,7 @@ mod cee_scape {
6969
use cee_scape::{call_with_sigsetjmp, SigJmpBufFields};
7070

7171
/**
72-
Given a closure that is assumed to be a wrapped Postgres `extern "C"` function, [pg_guard_ffi_boundary]
72+
Given a closure that is assumed to be a wrapped Postgres `extern "C-unwind"` function, [pg_guard_ffi_boundary]
7373
works with the Postgres and C runtimes to create a "barrier" that allows Rust to catch Postgres errors
7474
(`elog(ERROR)`) while running the supplied closure. This is done for the sake of allowing Rust to run
7575
destructors before Postgres destroys the memory contexts that Rust-in-Postgres code may be enmeshed in.
@@ -82,7 +82,7 @@ Wrapping the FFI into Postgres enables
8282
But only the first of these is considered paramount.
8383
8484
At all times PGRX reserves the right to choose an implementation that achieves memory safety.
85-
Currently, this function is used to protect **every** bindgen-generated Postgres `extern "C"` function.
85+
Currently, this function is used to protect **every** bindgen-generated Postgres `extern "C-unwind"` function.
8686
8787
Generally, the only time *you'll* need to use this function is when calling a Postgres-provided
8888
function pointer.

0 commit comments

Comments
 (0)