Asyncio not retrieving task exceptions
Closed this issue · 2 comments
@callumforrester as requested.
When using epicsadapter
, following an interrupt, the after_update
iterates through records allocated interrupt_records
, gets their current value from the device and sets it. The getter is user defined (in the device) the setter uses a pythonSoftIOC default. This can be found in softioc/device.py which defines the processing of epics devices.
On this setting call the following function is called to cast the type 'got' from the tickit device to the one appropriate to that record. Simply:
def _value_to_epics(self, value):
return self._ctype_(value)
If the value passed to this function from the device is not castable, eg. string -> float, Then it appears to hang the simulation.
If you then attempt to raise another interrupt, the simulation will crash with the error ERROR:asyncio:Task exception was never retrieved
.
The rest of the trace:
ERROR:asyncio:Task exception was never retrieved
future: <Task finished name='Task-10' coro=<TcpServer._generate_handle_function.<locals>.handle() done, defined at /workspace/tickit-devices/.venv/lib/python3.9/site-packages/tickit/adapters/servers/tcp.py:79> exception=AttributeError("'MasterScheduler' object has no attribute 'last_time'")>
Traceback (most recent call last):
File "/workspace/tickit-devices/.venv/lib/python3.9/site-packages/tickit/adapters/servers/tcp.py", line 99, in handle
tasks.append(asyncio.create_task(reply(await handler(data))))
File "/workspace/tickit-devices/.venv/lib/python3.9/site-packages/tickit/adapters/composed.py", line 42, in handle_message
await self.raise_interrupt()
File "/workspace/tickit-devices/.venv/lib/python3.9/site-packages/tickit/core/components/component.py", line 114, in raise_interrupt
await self.state_producer.produce(output_topic(self.name), Interrupt(self.name))
File "/workspace/tickit-devices/.venv/lib/python3.9/site-packages/tickit/core/state_interfaces/internal.py", line 168, in produce
await self.server.push(topic, Message(value=value))
File "/workspace/tickit-devices/.venv/lib/python3.9/site-packages/tickit/core/state_interfaces/internal.py", line 64, in push
await subscriber.add_message(message)
File "/workspace/tickit-devices/.venv/lib/python3.9/site-packages/tickit/core/state_interfaces/internal.py", line 145, in add_message
await self.callback(message.value)
File "/workspace/tickit-devices/.venv/lib/python3.9/site-packages/tickit/core/management/schedulers/base.py", line 73, in handle_message
await self.schedule_interrupt(message.source)
File "/workspace/tickit-devices/.venv/lib/python3.9/site-packages/tickit/core/management/schedulers/master.py", line 116, in schedule_interrupt
+ int((time_ns() - self.last_time) * self.simulation_speed)
AttributeError: 'MasterScheduler' object has no attribute 'last_time'
I thought it was curious that the exception (which it does produce) gets lost somewhere down the stack so that asyncio doesn't receive it.
I have found that the same (not so helpful) error message can be produced when sending an interrupting command to a simulated device when there is a typo in the configuration yaml. For example, try misspelling one of the shutter
s in shutter.yaml
and sending T=1
to the device when it's running.