register_hook(&mut HOOKS) : mutable reference to mutable static
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 ?
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.
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.
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.
Thanks for the explanations
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.