Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

p4p.client.thread.Context.put does not always work as expected when used inside a handler #164

Open
kurup opened this issue Jan 22, 2025 · 0 comments

Comments

@kurup
Copy link

kurup commented Jan 22, 2025

I'm trying to replicate similar functionality to how a forward link works in a traditional IOC using p4p.client.thread.Context.put in the handler for a PV however, I've run into an issue with this not always working depending on the order in which PVs are created. A simple example of the problem is:

from p4p.server import Server
from p4p.server.thread import SharedPV
from p4p.client.thread import Context
from p4p.nt import NTScalar

class MyHandler:
    def put(self, pv, op):
        pv.post(op.value())
        op.done()

class MyHandlerWithPut:
    def put(self, pv, op):   
        pv.post(op.value())
        op.done()
        ctxt = Context('pva')
        ctxt.put("DEV:RW:DOUBLE1",{})

pv1 = SharedPV(nt=NTScalar('i'), initial=0.0, handler=MyHandler())
pv2 = SharedPV(nt=NTScalar('i'), initial=0.0, handler=MyHandler())
pv3 = SharedPV(nt=NTScalar('i'), initial=0.0, handler=MyHandler())
pv4 = SharedPV(nt=NTScalar('i'), initial=0.0, handler=MyHandler())
pv5 = SharedPV(nt=NTScalar('i'), initial=0.0, handler=MyHandlerWithPut())

Server.forever(providers=[{
    "DEV:RW:DOUBLE1": pv1, 
    "DEV:RW:DOUBLE2": pv2, 
    "DEV:RW:DOUBLE3": pv3, 
    "DEV:RW:DOUBLE4": pv4,
    "DEV:RW:DOUBLE5": pv5 
    }])

The idea is that if I do a put to DEV:RW:DOUBLE5 this then triggers a put to DEV:RW:DOUBLE1. However, if I do a put to DEV:RW:DOUBLE5 (from another terminal) the server gives this error:

Unexpected
Traceback (most recent call last):
  File "/home/myuser/.local/lib/python3.10/site-packages/p4p/client/thread.py", line 362, in put
    value, i = done.get(timeout=timeout)
  File "/usr/lib/python3.10/queue.py", line 179, in get
    raise Empty
_queue.Empty

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/myuser/.local/lib/python3.10/site-packages/p4p/server/thread.py", line 19, in _on_queue
    M(*args)
  File "/mnt/c/Users/mysuser/Software/p4p_for_isis/examples/basic_server_recipe-testing.py", line 40, in put
    ctxt.put(put_pv,{})
  File "/home/myuser/.local/lib/python3.10/site-packages/p4p/client/thread.py", line 365, in put
    raise TimeoutError()
TimeoutError
Error from WorkQueue w/ functools.partial(<function _on_queue at 0x7f771b1bca60>, <p4p._p4p.ServerOperation object at 0x7f771b1b3be0>, <bound method MyHandlerWithPut.put of <__main__.MyHandlerWithPut object at 0x7f771b1ec7f0>>, SharedPV(value=0), <p4p.server.raw.ServOpWrap object at 0x7f771b1eca30>)
Traceback (most recent call last):
  File "/home/myuser/.local/lib/python3.10/site-packages/p4p/util.py", line 56, in handle
    callable()
  File "/home/myuser/.local/lib/python3.10/site-packages/p4p/server/thread.py", line 27, in _on_queue
    op.done(error=str(err))
  File "src/p4p/_p4p.pyx", line 888, in p4p._p4p.ServerOperation.done
ValueError: Must provide error message

The odd thing is the above code works if I change the link to point to any of the other pvs (e.g. DEV:RW:DOUBLE2). This also works if I create another pv between pv1 and pv5. Diggging about in the code I found that I can fix this by changing the number of workers defined in the __init__ method of the class _DefaultWorkQueue in p4p.util, i.e. if I use def __init__(self, workers=5):

It looks like this problem occurs for the specific configuration of having 5 pvs in a row with the last one linking to the first. I'm not sure if this is a bug or if there is a different way to call a put to a pv from within a handler. This issue may also be related to #144

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant