Yarp: Error when trying to use yarp::Thread in Python bindings

Created on 2 Sep 2019  路  6Comments  路  Source: robotology/yarp

Describe the bug
I implemented a sub-class of yarp::Thread using YARP's Python bindings, but get a
SWIG:DirectorMethodException when executing the script. The precise error message is:

terminate called after throwing an instance of 'Swig::DirectorMethodException'
what(): SWIG director method error. Error detected when calling 'Thread.threadInit'

To Reproduce
Create a sub-class of yarp::Thread using the Python bindings and try to instantiate it

Expected behavior
I would expect it to instantiate the Thread as a new object

Configuration (please complete the following information):

  • OS: Debian Linux
  • yarp version: 3.1.0+184

    • compiler: gcc 6.3.0

Additional context
I noticed that none of the very few python scripts in any of the robotology sub-repositories, that make use of multi-threading use YARP's own multi-threading functionality. All of them use native Python multi-threading libraries instead. This is what I am intending to do now as well but I thought it might be useful to solve this bug or, at least, understand somewhat better what causes it.

YARP v3.2.0 Bindings Bug Not an Issue

All 6 comments

I think yarp threads should not be used with bindings, and the native implementation should be used instead. Nonetheless yarp::Thread should either work or not be created at all...
If it doesn't work, I vote for removing it.

I kind of suspected something like that. I agree that, if it doesn't work, it's better not to see it in the bindings at all. I'm not a SWIG specialist, so I don't know how to stop it from generating those parts of the interface that deal with multi-threading.

I can replicate the error with the following code:

import yarp
class MyThread(yarp.Thread):
    def run(): # or initThread(): to get the exact error
        print("hi")
yarp.Network() # or yarp.Network.init()
x = MyThread()
x.start()

Edited my above comment, was missing the x.start() line.

Unordered comments:

  • Unfortunately, binding errors are hard to debug, SWIG:DirectorMethodException can appear even when issues are completely unrelated to SWIG.
  • RFModule examples (1, 2) are still working (which is good).
  • Long ago I played around inheriting from the RateThread class (now PeriodicThread). It worked, but things were laggy, so I ended up going for a more Pythonic solution.
  • As a YARP Python binding user, nothing against hiding this specific component as proposed above. As a general best practice, I guess we should favour idiomatic solutions, similar to using time.sleep rather than the YARPy equivalent.

After a couple of tests, I realized that this works:

import yarp
class MyThread(yarp.Thread):
    def run(self):
        print("hi")
yarp.Network()
x = MyThread()
x.start()

The only change is this one:

-    def run():
+    def run(self):

Probably relevant:

This works:

    def run(self):
        yarp.delay(0.5)

This doesn't work:

    def run(self):
        time.sleep(0.5)

```
terminate called after throwing an instance of 'Swig::DirectorMethodException'
what(): SWIG director method error. Error detected when calling 'Thread.run'



This again works:

```python
import time
# [...]
    def run(self):
        time.sleep(0.5)
Was this page helpful?
0 / 5 - 0 ratings