py_trees icon indicating copy to clipboard operation
py_trees copied to clipboard

How to call setup() method from non-main thread?

Open JakobDomislovic opened this issue 3 years ago • 2 comments

I am doing setup() method (from py_trees.trees.BehaviourTree()) in non-main thread and I am getting following error: ValueError: signal only works in main thread. How to deal with this without transferring setup() method in the main thread? I am also providing the whole trace below :)

File "/usr/src/***/***/***/behavior_trees/tree.py", line 40, in test_tree
    behaviour_tree.setup(timeout=15.0)
    │              └ <function BehaviourTree.setup at 0x7f59a7feb3a0>
    └ <py_trees.trees.BehaviourTree object at 0x7f59a4068d60>

  File "/usr/local/lib/python3.8/site-packages/py_trees/trees.py", line 324, in setup
    setup(
    └ <function setup at 0x7f59a7fe3280>
  File "/usr/local/lib/python3.8/site-packages/py_trees/trees.py", line 109, in setup
    signal.signal(
    │      └ <function signal at 0x7f59b537e3a0>
    └ <module 'signal' from '/usr/local/lib/python3.8/signal.py'>
  File "/usr/local/lib/python3.8/signal.py", line 47, in signal
    handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
              │       │      │            │           │            └ functools.partial(<function setup.<locals>.signal_handler at 0x7f59a40d9ca0>, original_signal_handler=<Handlers.SIG_DFL: 0>)
              │       │      │            │           └ <function _enum_to_int at 0x7f59b537e310>
              │       │      │            └ <Signals.SIGUSR1: 10>
              │       │      └ <function _enum_to_int at 0x7f59b537e310>
              │       └ <built-in function signal>
              └ <module '_signal' (built-in)>

ValueError: signal only works in main thread

JakobDomislovic avatar Aug 18 '21 16:08 JakobDomislovic

You could subclass BehaviourTree and write your own setup method that handles things as you need to. There's actually not much to the setup function, so this should not be too hard. See https://github.com/splintered-reality/py_trees/blob/devel/py_trees/trees.py#L47 - it's just using a threaded timer that relays to a callback that triggers the kill signal.

You could instead replace that with something that logs to the screen (downside: doesn't save you from a setup which hangs - you'll have to kill it from the outside).

Alternatively, if your paradigm permits it, you can use the multiprocessing module. See https://github.com/splintered-reality/py_trees/commit/d7be59dd9944ecbd5ecfb41d8f0fd00fe99daad1 for details.

stonier avatar May 30 '22 17:05 stonier

If you decide on something generic that you think others might make use of, let me know - we can replace, or at least implement an alternative pathway for setup in this library.

stonier avatar May 30 '22 17:05 stonier