Some context: I have a task that is responsible for generating procedural data on the GPU and store it in a texture. As I don’t want to generate dozen of textures per frame, I created a task that will fetch the requests from a queue, and notify the waiting task once the generation is done. To perform this notification I’m trying to use a future. The requesting task will await on the future and the generator task will use set_result to notify that task that the texture is ready (and send back the texture).
However while testing this, I encountered several weird stuff, and often segfault; Here is a code that tries to reproduce the problem :
:task(error): PythonTask ex_test exception was never retrieved:
Traceback (most recent call last):
File "/tmp/test.py", line 21, in main_task
t = result.get_result()
AttributeError: 'panda3d.core.Texture' object has no attribute 'get_result'
…which makes sense, because await returns the result already, not the future itself.
Is there something different about your build? Are you compiling with optimizations?
The pointer value is still the same as the one set in set_result(), so something in the texture object has been corrupted.
On a side note, I don’t know if that’s expected or not, but ref_ptr is a nullptr. It seems that the code has used set_result(TypedObject *result) I would have expected set_result(TypedReferenceCount *result) as I believe Texture inherit from ReferenceCount.
Edit: calling get_type() in set_result() works and correctly returns ‘Texture’ so the object is either corrupted or garbage collected before reaching get_done_result()
You can try putting an abort() in the texture destructor and get a stack trace to see when it gets destroyed.
However, ref_ptr is supposed to be set for correct reference management, so I wonder if this is an issue with selecting the correct overload. I suppose you are calling set_result() from Python, so the overload resolution is done by interrogate—maybe interrogate has a bug in its overload resolution? Did you compile Panda yourself, if so, can I see the libp3event_igate.cxx?
Hiding the set_result() overload that takes a TypedObject from interrogate might do it.
Indeed, if I keep a reference to the generated texture, the code above works fine, so it’s definitively a reference count problem.
If Ì comment out the section related to TypedObject in libp3event_igate.cxx it also solves the problem. I guess hiding from interrogate that overload would do the trick.
Here is the full set_result wrapper generated by interrogate :
Side question, that perhaps warrants its own discussion thread, set_result() requires a “pure” Panda3D object, is it possible to add support for plain Python object too or is there some limitations that prevent this ? (Or is it a way to piggyback the Python object using a Panda object ?)
Wow, thanks a lot ! (I was about to say that in the meantime one could use PandaNode and set_python_tag, but I didn’t even had the time to write it that you’re back with the full implementation )