-
-
Notifications
You must be signed in to change notification settings - Fork 586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix crash using Ref<T> as parameter #1045
Conversation
I tested this locally and it fixes the issue on my end (well at least for Hope this gets merged in time for the next maintenance release. GDExtension is basically unusable like this for non trivial tasks. |
@akien-mga Can you please also review this PR? It is simular with "Object*" PR which was approved. |
Thanks! |
Cherry-pick to 4.0 I suppose? |
This PR breaks the current master for overriding For example, the code below crashes immediately when any event is received. class MyContainer : public PanelContainer
{
GDCLASS(MyContainer , PanelContainer);
public:
static void _bind_methods() {}
void _input(const Ref<InputEvent>& event) override;
}; I have confirmed that it won't crash if I revert L269 to the original code return Ref<T>(reinterpret_cast<T *>(godot::internal::gde_interface->object_get_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)), godot::internal::token, &T::___binding_callbacks))); @zhehangd @akien-mga Could you, please double-check this PR? |
Did a quick test and confirmed that the crash is real. void call_with_arg_by_value(godot::Ref<godot::Image> image); // ok
void call_with_arg_by_ref(const godot::Ref<godot::Image>& image); // ok
void _input(const godot::Ref<godot::InputEvent>& event) override; // crash I initially thought it was a problem between passing I can think of two hypotheses:
Let me know if there are other clues. |
The former version of core also had same sort of pointer indirection bug #677 and that was fixed by me. I'm eager to learn the rationale of current master (what's going on inside the core?) so that we would hopefully never going to need to fix this every year... |
It does, as it was discussed in #958 (which this PR reverted) and godotengine/godot#69902 . Not sure what the proper solution is, but as a note to extensions developers, if you are using this virtual methods which take or return refs (e.g. WebRTC, ImageLoaders, etc) you should revert this PR (and probably avoid using |
@BastiaanOlij Why were the encodings diverged in the first place? Is there any technical reasons why virtual methods require Ref arguments to be encoded by pointer? I'm afraid that I'm not fully convinced by the description in godotengine/godot#69902. What is going on with the ownership of PtrToArg is only aware of parameter types (it doesn't know about caller/callee) so it seems impossible to fix this issue by just altering |
I'll add this to the agenda for the next GDExtension meeting, but I think we should add a CI step to godot-cpp that builds and runs a test GDExtension where we try to excercise some of these tricky cases. It's hard to keep track of all the past issues and avoid reverting/regressing old fixes |
@saki7 thats a bit of a story :) The root problem is that the Because we're passing pointers to the godot object we have a possibility that the So there are a bunch of scenarios where we've got a When we look at calls that go through our script system, so the same system that GDScript uses, we actually use However When virtual function support was introduced we wanted to support any C types that are used in many cases, so instead of using Variants we used normal C types. That works for everything except |
Thanks for the explanation :)
Note row 3 and row 4, in these cases GDExtension expects same parameter types, i.e. @BastiaanOlij Sorry to bother you, but could you clarify the proper solution for this problem? |
@saki7, Couple of things that do not seem right though you are close to it.
The pointer to an object on the Godot side is meaningless in godot-cpp, there is some magic happening that checks if we already have created a wrapper object on the godot-cpp side and it will use that, else it will create a wrapper object.
(note that when you have return values, we actually sent that as a parameter to godot-cpp, I think it's added at the end but it could also be the first argument, I'm not sure) |
@BastiaanOlij Thanks again for the description 👍 |
For this specific issue, I propose a test matrix like this:
Total: 2 * 3 * 2 * 4 = 48 cases |
We discussed this issue on GDExtension meeting today. Impacts
Possible solutions
Documentation
Testing
|
We should probably move this discussion into a separate issue instead of keeping this going on a merged PR :) |
Perhaps this PR should be reverted while we come up with a better solution? |
Yes I think this PR should be reverted for now. There's much more use-cases for overriding virtual methods. And if we can't override virtual methods then there's technically no workaround. |
I have been temporarily away from Godot to focus on some other stuff, and it isn't easy to closely catch up. Sorry for that. |
Btw, if you guys decide to revert, remember that in the previous version |
@akien-mga i could reproduce this crash with both 4.0.1 and 4.0.2 tags, and in 4.0 branch (which right now matches 4.0.2 tag) |
No, please don't cherry-pick. As we mentioned above, this PR contains regression. I really appreciate the effort taken by the PR author, however it had been confirmed by the contributors that the root cause of this issue is pretty much non-trivial. No offense, but I suggest you patch your own repo until this is completely fixed. |
…standardize on `Object **` encoding in ptrcall
Fixes #1021 and fixes #1024 which are exactly the same issue.
In GDScript VM we have
It extracts the underlying data pointers from parameter variants -- ,
Object*
for objects -- and callptrcall
.In our GDExtension code, we may declare a method like this
Godot-cpp will generate the code that binds it with GDExtension API.
For example, it could use (in
binder_common.hpp
)And for
Ref<Foo>
it callsgodot-cpp/include/godot_cpp/classes/ref.hpp
Line 268 in f5133c0
Now here is the problem.
The engine-provided
p_ptr
isFoo*
, whilegodot-cpp
assumes it isRef<Foo>*
and tries to getFoo*
fromRef<Foo>::ptr()
, which naturally causes a crash.This issue comes from the attempt to fix
Ref
return issue. See #958.It turns out that only
encode
needs to be changed to setRef
on the engine side,convert
should remains the same working with raw object pointers.Hilariously, the previous implementation of
convert
before #958 was also wrong. It treatedp_ptr
asObject**
, same as the issue in #1044.