pgrx icon indicating copy to clipboard operation
pgrx copied to clipboard

register_hook(&mut HOOKS) : mutable reference to mutable static

Open daamien opened this issue 1 year ago • 5 comments

Not a actually bug, but a strange warning....

I registered my hooks with the following line

        static mut HOOKS: AnonHook = AnonHook { };
        pgrx::hooks::register_hook(&mut HOOKS)

which I copy-pasted blindly from the hook_tests here:

https://github.com/pgcentralfoundation/pgrx/blob/2c1d3887d16744e5230efe506d98a51836cf8228/pgrx-tests/src/tests/hooks_tests.rs#L126C1-L127C46

Cargo 1.77 issues the following warning

473 |     pgrx::hooks::register_hook(&mut HOOKS);
    |                                ^^^^^^^^^^ mutable reference to mutable static
    |
    = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
    = note: this will be a hard error in the 2024 edition
    = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior
    = note: `#[warn(static_mut_refs)]` on by default
help: use `addr_of_mut!` instead to create a raw pointer
    |
473 |     pgrx::hooks::register_hook(addr_of_mut!(HOOKS));

Trying to rewrite that register_hook line to remove the warning, I ended up with the syntax below that seems to please cargo but looks fishy

        let h = &mut *std::ptr::addr_of_mut!(HOOKS) as &mut dyn PgHooks;                                                                         
        pgrx::hooks::register_hook(h);

I tried to understand the issue 114447, but it is way out of my league....

It seems obvious that we won't create another reference to the HOOKS variable, but is that enough to simply ignore this warning ?

daamien avatar Jul 04 '24 12:07 daamien

We are going to move away from using static mut in pgrx. The use here is actually quite inappropriate and almost certainly UB, because we later do materialize references to it inside the various hooks:

https://github.com/pgcentralfoundation/pgrx/blob/2c1d3887d16744e5230efe506d98a51836cf8228/pgrx/src/hooks.rs#L601-L608

So I don't think

It seems obvious that we won't create another reference to the HOOKS variable

is quite correct.

Fixing this requires a redesign of the API.

workingjubilee avatar Jul 05 '24 01:07 workingjubilee

Trying to rewrite that register_hook line to remove the warning, I ended up with the syntax below that seems to please cargo but looks fishy

        let h = &mut *std::ptr::addr_of_mut!(HOOKS) as &mut dyn PgHooks;                                                                         
        pgrx::hooks::register_hook(h);

And you are correct that this is exactly 0% better, by the way.

workingjubilee avatar Jul 05 '24 02:07 workingjubilee

I believe the initial "reborrow" of current_hook is not UB but the borrow we do inside prev of each specific prev_whatever_hook is?

It would probably be useful if someone created a "small-scale model" of the "triggering a hook" sequence of events, with a much-pared-back version of our hooks API, and ran it through Miri. I think it might be possible to fix the biggest hooks API UB with mostly-internal changes.

workingjubilee avatar Jul 05 '24 02:07 workingjubilee

Thanks for the explanations

daamien avatar Jul 05 '24 09:07 daamien

It would probably be useful if someone created a "small-scale model" of the "triggering a hook" sequence of events, with a much-pared-back version of our hooks API, and ran it through Miri. I think it might be possible to fix the biggest hooks API UB with mostly-internal changes.

I’d be up to try and do that.

As of 0.12, we are stuck with using an unsound and deprecated API with no alternative, as we need to intercept utility commands in our extension.

EdMcBane avatar Sep 27 '24 14:09 EdMcBane