throttleRecord: write link-status flags for the correct link#29
Open
physwkim wants to merge 1 commit into
Open
throttleRecord: write link-status flags for the correct link#29physwkim wants to merge 1 commit into
physwkim wants to merge 1 commit into
Conversation
special() marked outLinkStat unconditionally in the off-IOC branch even for a .SINP change, and checkLink() carried caLink/caLinkNc across the OUT/SINP loop so SINP's status could be written from OUT's connection state. Select plinkStat per field in special(), and scope caLink/caLinkNc per loop iteration so each link's status is computed only from its own link. init_record was already correct and is left untouched.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
throttleRecord: write link-status flags for the correct link
Summary
throttleRecordkeeps two per-link diagnostic status fields —outLinkStatfor the output (
OUT) link andsinpLinkStatfor the sync-input (SINP)link. Each holds
NOT_CA_LINK/CA_LINK_OK/CA_LINK_NOT_OKand is meantto reflect the connection state of its own link.
init_recordandcheckLinkalready select a per-linkshort *plinkStat(pointing atoutLinkStatorsinpLinkStat) and write through it. Two other placesviolate the "each flag reflects its own link" invariant: one writes the wrong
field by name, the other reads a stale value carried over from the previous
loop iteration. This PR fixes both so every write targets the link actually
being processed.
These are wrong-variable / stale-variable writes into diagnostic
link-status flags. They are not a crash, memory-safety, or data-loss bug —
graded Low impact (see below).
Site 1 —
special(),.OUT/.SINPchange naming an off-IOC PVWhen an operator changes
OUTorSINPto a PV that is not on this IOC, the"pv is not on this ioc" branch scheduled a connection-status callback and set:
special()already dispatchesplink/plinkValidonfieldIndex == throttleRecordOUTvsthrottleRecordSINP, but it had noplinkStatin that dispatch, so the hardcoded write always marked the OUTlink — even for a
.SINPchange. Result: a.SINPchange to an off-IOC PVflagged
outLinkStat(the wrong link) and never setsinpLinkStat.Fix: add
short *plinkStatto the existing field dispatch (pointing at&prpvt->outLinkStatforOUT,&prpvt->sinpLinkStatforSINP, mirroringinit_record/checkLink) and write*plinkStat = CA_LINK_NOT_OK;.Site 2 —
checkLink(), stalecaLink/caLinkNcacross the link loopcheckLinkloopsfor (i = 0; i < 2; i++)over the OUT (i==0) and SINP(
i==1) links, and at the end of each iteration writes that link's status:But
caLinkandcaLinkNcwere declared once, outside the loop and wereonly ever assigned inside
if (plink->type == CA_LINK). On thei==1(SINP) pass, if SINP is not a CA link that block is skipped, so the status
write used the stale
caLink/caLinkNcvalues left over from thei==0(OUT) iteration. A disconnected CA OUT link (
caLinkNc == 1) therefore forcedsinpLinkStat = CA_LINK_NOT_OKeven when SINP was perfectly fine (e.g. aconstant or a local link).
Fix: move the
caLink/caLinkNcdeclarations inside the loop body so eachiteration starts from a clean
0/0by construction — no carryover isrepresentable. (Equivalent to resetting both at the top of each iteration, but
scoping them per-iteration makes the reset structural rather than a manual
step a future edit could drop.)
Impact — Low
Both bugs land only in the diagnostic link-status flags, not in the record's
value or output:
outLinkStatself-heals: the nextcheckLinkpass (scheduled connectionpoll, or a
process()on a CA OUT link) recomputes it from the realconnection state.
.SINPat an off-IOC PV briefly sees theOUT link flagged not-connected instead of SINP, until the next
checkLinkcorrects both — a misleading diagnostic, not a functional fault.checkLinkreportsinpLinkStatas
CA_LINK_NOT_OKeven when SINP is connected or non-CA — again a wrongdiagnostic value, corrected on the next pass once SINP's own state is
evaluated cleanly.
No overstatement intended: neither bug corrupts the throttled value, drops a
callback, or affects link behaviour — only the reported per-link status.
Family check
Anchor: every
outLinkStat/sinpLinkStat/plinkStat/caLink/caLinkNcread and write instdApp/src/throttleRecord.c.special()— addedplinkStatto the field dispatch; the off-IOC branchnow writes
*plinkStatinstead of the hardcodedprpvt->outLinkStat.checkLink()—caLink/caLinkNcscoped per loop iteration.init_record()— already selectsplinkStatper link and writes*plinkStat(both theNOT_CA_LINKinit and the off-IOCCA_LINK_NOT_OK); untouched.init_recordschedule check(
outLinkStat == CA_LINK_NOT_OK || sinpLinkStat == CA_LINK_NOT_OK) and theprocess()check (outLinkStat != NOT_CA_LINK→checkLink) — reads ofthe correct field for their purpose; no wrong-link write.
checkLinkend-of-loop writes through*plinkStatwere alreadyper-link correct; only their
caLink/caLinkNcinputs were stale.No third site writes the wrong link.
Testing
Not compiled locally — no EPICS support tree / std build is configured in this
worktree. The change is a source-only edit relying on CI to compile. Expected
before/after behaviour:
caput <rec>.SINP <off-ioc-pv>now flagssinpLinkStat(was
outLinkStat).OUTlink,checkLinkno longer forcessinpLinkStat = CA_LINK_NOT_OKwhenSINPis connected or non-CA.paths).