dbCa subscribes twice to ENUM

Bug #1786320 reported by mdavidsaver
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
EPICS Base
Status tracked in 7.0
3.14
Fix Released
Undecided
Andrew Johnson
3.15
Fix Released
Undecided
Andrew Johnson
3.16
Fix Released
Undecided
Andrew Johnson
7.0
Fix Released
Undecided
Andrew Johnson

Bug Description

Wayne Lewis and Krisztian Löki (ESS) report:

On 08/09/2018 08:26 AM, Wayne Lewis wrote:
> It looks like a camonitor to an ENUM type field (e.g., MBBI.VAL)
> actually produces two monitors, one with the numeric value and one with
> the string value. This can result in a record using CP/CPP processing on
> an input link pointing to the ENUM field being processed twice for each
> change in the ENUM field. Is this assessment correct?
>
> The following is a summary of the database where we see this behaviour:
>
> record(mbbi, "mbbi")
> {
> field(TPRO, "1")
> field(ZRST, "zero")
> field(ONST, "one")
> field(TWST, "two")
> }
>
> record(sseq, "sseq")
> {
> field(TPRO, "1")
> field(DOL1, "mbbi CP")
> }
>
> In most cases, we see the following on the IOC console:
>
> epics> ca:<email address hidden>: Process mbbi
> scanOnce: Process sseq
> scanOnce: Active sseq
>
> Does the 'scanOnce: Active sseq' line mean that the second monitor arrived
> while the record was still processing and is being ignored?
>
> However, occasionally the 'scanOnce: Active sseq' changes to 'scanOnce: Process
> sseq', suggesting that the record managed to finish processing before the
> second monitor arrived.

On 08/09/2018 10:27 AM, Krisztian Löki wrote:
> I've tested with base-3.15.4 and was able to replicate with base records; changed 'sseq' to 'stringin' (and DOL1 -> INP). Moreover, putting the records to separate databases and loading them into two different IOCs enabled me to use wireshark with your ca.lua. There are definitely two different CA events sent; one for the integer value and one for the string value.

Revision history for this message
mdavidsaver (mdavidsaver) wrote :

I can replicate. There is an added wrinkle that apparently a link from ao.DOL doesn't setup two, but stringin.INP does.

> ca:mdavidsaver@md-laptop: Process mbbi
> scanOnce: Process sseq2
> scanOnce: Process sseq1
> scanOnce: Process sseq2

record(mbbi, "mbbi")
{
    field(TPRO, "1")
    field(ZRST, "zero")
    field(ONST, "one")
    field(TWST, "two")
}

record(ao, "sseq1")
{
    field(TPRO, "1")
    field(DOL , "mbbi CP")
    field(OMSL, "closed_loop")
}

record(stringin, "sseq2")
{
    field(TPRO, "1")
    field(INP , "mbbi CP")
}

Changed in epics-base:
status: New → Confirmed
Revision history for this message
Andrew Johnson (anj) wrote :

I can explain what's happening, and guess why it was implemented this way.

Internally dbCa has 2 ways of subscribing for monitor updates, which can coexist: As the native type, and as a string. All dbCa input links subscribe for the value in the channel's native type when they first connect. This ensures that a CP/CPP link will process the record when the channel connects.

A string subscription gets added when the native type of the channel is DBF_ENUM and the record or device support calls dbCaGetLink(plink, DBR_STRING, ...). I guess this was added to get around the fact that for a long time there was no way to ask for updates whenever an ENUM's choice strings changed. If you did the conversion from the native ENUM value to a string locally on the client like we do for all of the other data types, you would get it wrong as soon as someone modifies the choice strings.

So a stringin record monitoring an ENUM channel has two subscriptions, which is exactly what you're seeing. What we *want* to happen in this case is for only the string subscription to trigger the record to process. Making that happen isn't actually very difficult, the attached patch against the 3.14 branch implements this.

However at the initial connection (or re-connection for remote links) the stringin record will still process twice. That's because it isn't until the record actually processes for the first time that the stringin device support calls dbCaGetLink(plink, DBR_STRING, ...) which is what causes the second monitor to be set up. The dbCaGetLink() code cannot block waiting for that to happen, but it should put the record into an INVALID/LINK alarm state the first time. The second scan gives the right value.

I might be able to fix the latter in EPICS 7, but it isn't really possible in earlier series.

I have not tested this patch heavily, other than to confirm that it appears to fix this issue.

- Andrew

Revision history for this message
Andrew Johnson (anj) wrote :

I committed the above fix to the 3.14 branch.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.