tobspr / LUI

Lightweight User Interface for Panda3D
MIT License
84 stars 24 forks source link

[Thread Safety]'set_text()' on a LUILabel causes AssertionError if called from secondary Thread #50

Open Nel-Fie opened 6 years ago

Nel-Fie commented 6 years ago

I've implemented a thread from direct.stdpy.threading in a project, and the function set_text() is sometimes called from that thread (i.e. not 'Main Thread'). Most of the time this simply causes the text not to update properly or to be incomplete/glitched when rendered, but it occasionally causes an AssertionError that crashes the P3D app, with the following error message:

File "C:\Program Files\Python36\lib\site-packages\lui_builtin\LUILabel.py", line 62, in set_text
    self._text.text = str(text)
AssertionError: _sprite_index >= 0 at line 264 of A:\Programming\LUI-master\source\luiSprite.cxx

Process finished with exit code 255

The exit code is not always the same. The error is caused by the Main Thread rendering a frame while the secondary thread is still operating on the LUI Label.

Until a LUI-internal solution is worked out, here's a workaround that might help those facing this problem:

  1. Get a render lock via base.graphicsEngine.getRenderLock() and store it at hand of whatever code that will call on your LUI object(s) from another thread. (e.g. store it as self.lock = base.graphicsEngine.getRenderLock())
  2. Before your call to a function from your LUI object(s), get your render lock. (e.g. lock = self.lock)
  3. Call lock.acquire().
  4. Perform whatever call or other operations you need on your LUI object(s).
  5. Call lock.release().

This ensures that the Main Thread will wait for the call to finish before rendering the frame.

Credits: All information about this error as well as the workaround were provided by rdb over the P3D IRC channel.