Wrong representation of unsigned types on the client
Closed this issue · 7 comments
Hi Michael,
While doing some tests with unsigned types, I discovered that the client is not representing the values for the higher half of the range for unsigned types correctly. The server part seems to be working well with unsigned types.
For example, this PV:
$ pvget TYPES_TEST:PV:USHORT
TYPES_TEST:PV:USHORT 2023-03-20 09:09:49.177 48303
Gets this result using p4p-4.1.2:
ctxt.get('TYPES_TEST:PV:USHORT')
18446744073709534383
It seems the conversion is done in 2 steps:
- 48303 is represented as a signed short: 2**16 - 1 - 48303 = -17232
- The previous value is converted to unsigned long: 2**64 - 1 - 17232 = 18446744073709534383
This seems to be a regression introduced when upgrading p4p to use pvxs, because I don't see the issue using v3.5.
I forgot to mention, this issue does not affect arrays, only scalar PVs.
For completeness, what is serving TYPES_TEST:PV:USHORT
?
... and what does pvinfo TYPES_TEST:PV:USHORT
show?
That PV came from a rather large structure, so I prepared a minimal reproducible example using p4p:
from p4p.nt import NTScalar
from p4p.server import Server
from p4p.server.thread import SharedPV
pv = SharedPV(nt=NTScalar('B'),
initial=2**7)
@pv.put
def handle(pv, op):
pv.post(op.value())
op.done()
Server.forever(providers=[{
'demo:pv:ubyte':pv,
}])
Using pvget
:
$ pvget demo:pv:ubyte
demo:pv:ubyte <undefined> 128
Using p4p-4.1.2
>>> from p4p.client.thread import Context
>>> ctxt = Context()
>>> ctxt.get('demo:pv:ubyte')
18446744073709551488
And pvinfo
output:
$ pvinfo demo:pv:ubyte
demo:pv:ubyte
Server: X.X.X.X:5075
Type:
epics:nt/NTScalar:1.0
ubyte value
alarm_t alarm
int severity
int status
string message
time_t timeStamp
long secondsPastEpoch
int nanoseconds
int userTag
I think this issue is fixed by epics-base/pvxs@7d16ab3. Can you confirm?
Yes, that fixes the issue. I tested all unsigned types successfully.
Thanks for fixing it so quickly!
Fix released as pvxslibs==1.1.3
.