dls-controls / pythonSoftIOC

Embed an EPICS IOC in a Python process
Apache License 2.0
32 stars 7 forks source link

ctype cast hangs when casting to incompatable types #100

Closed abbiemery closed 1 year ago

abbiemery commented 1 year ago

The _value_to_epics function in softioc/device.py hangs if the value cannot be cast as self._ctype_.

def _value_to_epics(self, value):
        return self._ctype_(value)

I found this issue when using the epics adapter with a tickit device, if you get it wrong it just hangs. It would be useful to have this return an exception if this occurs instead of hanging. Then it can be passed as a task exception and won't break the simulation in a way that is more difficult to trace.

AlexanderWells-diamond commented 1 year ago

Thank you for the report. Do you have an example of a value that would cause an issue? I'm uncertain what you're trying to store in a record that could cause this. What initial_value is the record given?

abbiemery commented 1 year ago

It occurred when accidentally passing a string type to a numeric type record. Both an aIn record and an mbbi record. Obviously them being string types was an error on my side, but it took a bit of digging to realise it this cast was holding things up.

Araneidae commented 1 year ago

Hmm. Can't reproduce this. On aIn and mbbi the _ctype_ field is set to ctypes.c_double and ctypes.c_uint16 respectively, and I get an ordinary TypeError exception when calling either of these on a string:

>>> ctypes.c_double("Not a number")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be real number, not str
AlexanderWells-diamond commented 1 year ago

Afraid I can't reproduce it either. This example deliberately tries to set a string into an aIn record and it throws an exception on startup:

# Import the basic framework components.
from softioc import softioc, builder, asyncio_dispatcher
# Create an asyncio dispatcher, the event loop is now running
dispatcher = asyncio_dispatcher.AsyncioDispatcher()

# Set the record prefix
builder.SetDeviceName("MY-DEVICE-PREFIX", initial_value="ABC")

# Create some records
ai = builder.aIn('AI')

# Boilerplate get the IOC started
builder.LoadDatabase()
softioc.iocInit(dispatcher)

# Finally leave the IOC running with an interactive shell.
softioc.interactive_ioc(globals())

Can you please provide a runnable example that shows the problem? Or a link to a repo we can check out and run?

And what version of PythonSoftIOC are you running?

abbiemery commented 1 year ago

The version is 4.0.2, I can share that, just sorting a branch to illustrate my issue. Can you all use dev containers on your work stations?

abbiemery commented 1 year ago

Closing this because we managed to trace the issue back into tickit. Thank you for the help :)

For those who are curious https://github.com/dls-controls/tickit/issues/79