toggle button/radiogroup combo works with wires, not vias
Closed this issue · 3 comments
The failure mode is this: clicking on the button in the right patch (or any stripped-down version of it that includes a send/receive pair in the feedback loop) locks up MFP until the request times out 5 seconds later. The traceback on timeout looks like this:
[ 42.503 main] [var]: calling gui_command.configure
[ 42.503 gui] configure: handing off to clutter thread
[ 47.508 gui] Exception while handling key command M1DOWN
[ 47.510 gui] Traceback (most recent call last):
[ 47.510 gui] File "/home/grib/devel/mfp/wafbuild/virtual/lib/python2.7/dist-packages/mfp-0.05_git_5abdd9b-py2.7.egg/mfp/gui/input_manager.py", line 175, in handle_event
[ 47.510 gui] rv = self.handle_keysym(keysym)
[ 47.511 gui] File "/home/grib/devel/mfp/wafbuild/virtual/lib/python2.7/dist-packages/mfp-0.05_git_5abdd9b-py2.7.egg/mfp/gui/input_manager.py", line 105, in handle_keysym
[ 47.511 gui] handled = handler[0]()
[ 47.512 gui] File "/home/grib/devel/mfp/wafbuild/virtual/lib/python2.7/dist-packages/mfp-0.05_git_5abdd9b-py2.7.egg/mfp/gui/modes/clickable.py", line 40, in click
[ 47.512 gui] return self.widget.clicked()
[ 47.512 gui] File "/home/grib/devel/mfp/wafbuild/virtual/lib/python2.7/dist-packages/mfp-0.05_git_5abdd9b-py2.7.egg/mfp/gui/button_element.py", line 202, in clicked
[ 47.513 gui] MFPGUI().mfp.send(self.obj_id, 0, message)
[ 47.514 gui] File "/home/grib/devel/mfp/wafbuild/virtual/lib/python2.7/dist-packages/mfp-0.05_git_5abdd9b-py2.7.egg/mfp/rpc/rpc_wrapper.py", line 19, in inner
[ 47.515 gui] return self.call_remotely(rpcdata)
[ 47.515 gui] File "/home/grib/devel/mfp/wafbuild/virtual/lib/python2.7/dist-packages/mfp-0.05_git_5abdd9b-py2.7.egg/mfp/rpc/rpc_wrapper.py", line 104, in call_remotely
[ 47.516 gui] self.rpchost.wait(r, timeout=5)
[ 47.517 gui] File "/home/grib/devel/mfp/wafbuild/virtual/lib/python2.7/dist-packages/mfp-0.05_git_5abdd9b-py2.7.egg/mfp/rpc/rpc_host.py", line 157, in wait
[ 47.517 gui] raise Exception()
[ 47.518 gui] Exception
The whole round-trip goes like this: Click, then send a bool to the underlying [var]
is the "outgoing" leg, then the [var]
calls configure
with its new value and updates the GUI as the "return" leg. The last message before the traceback is the "return" leg of the round trip.
What we see in the log (locally-added log statements, you'll have to trust me) is that we have handed off the update thunk to the Clutter thread but it never gets called. Why? Because the Clutter thread is still waiting for the click handler to return.
OK, that sorta makes sense, but the click handler should have returned very shortly after the "handing off to clutter thread" message. So the next step is to figure out why it's not.
More debugging output. This is a trace of everything that happens in a simplified version of the above patch when the toggle goes from False to True.
[ 26.394 gui] button: sending True to 1
[ 26.394 main] send: 1 0 True
[ 26.395 main] [var]: <mfp.builtins.var.Var object at 0x7ff961f3b750> triggered with [True, Uninit]
[ 26.395 main] [var]: checking True {'value': False, 'position_x': 98.61260986328125, 'name': 'toggle_001', 'width': 20, 'on_message': True, 'no_export': False, 'update_required': True, 'height': 20, 'num_outlets': 1, 'dsp_inlets': [], 'off_message': False, 'display_type': 'toggle', 'num_inlets': 2, 'position_y': 172.55679321289062, 'is_export': False, 'dsp_outlets': [], 'layername': 'Layer 0', 'scope': '__patch__'}
[ 26.395 main] [var]: calling gui_command.configure
[ 26.396 gui] configure: handing off to clutter thread
[ 26.396 main] [var]: returned from gui_command.configure
[ 26.396 main] [var]: <mfp.builtins.var.Var object at 0x7ff961f3b750> trigger done
[ 26.396 main] send: doing work item (<mfp.builtins.sendrcv.Send object at 0x7ff961f3b7d0>, True, 0) of 1
[ 26.397 main] [send]: triggered <mfp.builtins.sendrcv.Send object at 0x7ff961f3b7d0>
[ 26.397 main] [send]: in case 3 <mfp.builtins.sendrcv.MessageBus object at 0x7ff961f3b910>
[ 26.397 main] send: doing work item (<mfp.builtins.sendrcv.Recv object at 0x7ff961f3b850>, True, 0) of 1
[ 26.397 main] [recv]: [True, Uninit]
[ 26.397 main] send: doing work item (<mfp.builtins.radiogroup.RadioGroup object at 0x7ff961f3b990>, True, 0) of 1
[ 26.397 main] [radiogroup] <mfp.builtins.radiogroup.RadioGroup object at 0x7ff961f3b990>: triggered with [True, Uninit]
[ 26.397 main] [radiogroup] <mfp.builtins.radiogroup.RadioGroup object at 0x7ff961f3b990>: trigger done
[ 26.397 main] send: doing work item (<mfp.builtins.var.Var object at 0x7ff961f3b750>, True, 0) of 1
[ 26.397 main] [var]: <mfp.builtins.var.Var object at 0x7ff961f3b750> triggered with [True, Uninit]
[ 26.398 main] [var]: checking True {'value': True, 'position_x': 98.61260986328125, 'name': 'toggle_001', 'width': 20, 'on_message': True, 'no_export': False, 'update_required': True, 'height': 20, 'num_outlets': 1, 'dsp_inlets': [], 'off_message': False, 'display_type': 'toggle', 'num_inlets': 2, 'position_y': 172.55679321289062, 'is_export': False, 'dsp_outlets': [], 'layername': 'Layer 0', 'scope': '__patch__'}
[ 26.398 main] [var]: <mfp.builtins.var.Var object at 0x7ff961f3b750> trigger done
[ 26.398 main] send: doing work item (<mfp.builtins.sendrcv.Send object at 0x7ff961f3b7d0>, True, 0) of 1
[ 31.402 gui] Exception while handling key command M1DOWN
The key thing to note is that the same [send]
is mentioned twice here. i'm not sure why, but this may be a deadlock on the [send]
trigger lock. I would have thought the relaying of the message would be enough decoupled that this would not be a problem, but maybe not.
The commit above fixes this problem and makes the test patches work. It was in fact a deadlock on the trigger_lock, caused by the [send]
object's odd behavior of calling self.dest.obj.send()
in its trigger method to pass the object along.
The fix pulls the "message forwarding" out of the locked trigger method and into a custom _send.