Skip to content

fix(canopen): hold the peer SDO channel across a foreign PDO snapshot - #298

Merged
dborgards merged 1 commit into
mainfrom
fix/canopen-pdo-observer-channel
Oct 12, 2026
Merged

dborgards merged 1 commit into
mainfrom
fix/canopen-pdo-observer-channel

Conversation

@dborgards

Copy link
Copy Markdown
Owner

What does this change?

Closes #295. ObserveForeignPdoAsync read a peer's COB-IDs and mapping with one public upload each, so a caller to the same peer could take the SDO channel between two of them; the displaced upload was refused as in flight, which the observer took for "live record unavailable", and the observation combined a live COB-ID with the file's mapping. The observer now takes the peer's SDO channel without waiting and holds it for the whole snapshot, the rule #291 gave the SRDO observer: a caller arriving meanwhile is refused as in flight, a safety transaction waits, and a channel busy at the start makes the whole snapshot the file's.

Test: CanOpenForeignPdoObserveTests.A_call_cutting_in_mid_snapshot_is_refused_and_the_snapshot_stays_live — a public upload started in the AfterPdoMatchForTests seam, between the COB-ID match and the mapping read. Red on 2d5ba02 (the mapping came from the file), green after the change. The pinned fallback An_SDO_already_in_flight_falls_back_to_the_file_instead_of_throwing still holds. README (§SDO client, §Observing a peer PDO), the ICanOpenNode remarks and FR-CO-030 say so.

Type of change

  • feat — new behaviour (minor release)
  • fix / perf — bug or performance fix (patch release)
  • docs / test / refactor / chore / ci — no release
  • Breaking change (! in the title, plus a BREAKING CHANGE: footer explaining the migration)

Checklist

  • dotnet build CanKit.Pro.sln -c Release succeeds (-p:CI=true, 0 warnings)
  • dotnet test CanKit.Pro.sln -c Release passes (net10.0: 1884 tests; dotnet format --verify-no-changes clean; pack + verify-packages.py 9 packages ok; requirements traceability 0 new untraced)
  • Public API changes are documented with XML comments (no API change; ObserveForeignPdoAsync remarks updated)
  • New behaviour is covered by a test
  • The requirement or ADR this relates to is referenced: FR-CO-030

🤖 Generated with Claude Code

ObserveForeignPdoAsync read a peer's COB-IDs and mapping with one public
upload each, so another caller to the same peer could take the channel
between two of them; the displaced upload was refused as in flight, the
observer took that for "live record unavailable", and the observation
combined a live COB-ID with the file's mapping. #295.

The observer now takes the peer's SDO channel without waiting and holds
it for the whole snapshot, as the SRDO observer does since #291: a
caller arriving meanwhile is refused as in flight, a safety transaction
waits, and a channel busy at the start makes the whole snapshot the
file's. The live reads go through the LiveUpload delegate; the match
and decode helpers are static over it.

Test: A_call_cutting_in_mid_snapshot_is_refused_and_the_snapshot_stays_live
(a public upload started in the AfterPdoMatchForTests seam), red on
2d5ba02 with the mapping taken from the file. README, ICanOpenNode and
FR-CO-030 say so.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes peer SDO concurrency and foreign-PDO decode semantics when the channel is contended; behavior is covered by new and existing tests but affects master-tool timing with safety transactions and concurrent SDO.

Overview
Fixes #295: ObserveForeignPdoAsync could mix a live COB-ID with the EDS/DCF mapping when another SDO call to the same peer ran between the observer’s COB-ID and mapping uploads—the displaced upload was treated as “live unavailable” and fell back to the file.

ObserveForeignPdoAsync now matches the SRDO observer: it claims the peer SDO channel without waiting (PeerSdoChannel, non-blocking Wait(0)) and holds it for the whole live snapshot, routing all COB-ID/mapping reads through a LiveUpload delegate (SdoUploadCoreAsync or synthetic “already in flight”). Concurrent SDO calls to that peer are refused; safety transactions wait; if the channel was busy at the start, the entire snapshot uses the file. Adds test seam AfterPdoMatchForTests and integration test A_call_cutting_in_mid_snapshot_is_refused_and_the_snapshot_stays_live.

FR-CO-030, ICanOpenNode remarks, and README (SDO client + observing peer PDO) document snapshot semantics and in-flight behavior.

Reviewed by Cursor Bugbot for commit 157e7ad. Bugbot is set up for automated code reviews on this repo. Configure here.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-12T10:31:40.136348Z 157e7ad PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@codecov

codecov Bot commented Oct 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@dborgards
dborgards merged commit 4e45f3c into main Oct 12, 2026
15 checks passed
@dborgards
dborgards deleted the fix/canopen-pdo-observer-channel branch October 12, 2026 10:56
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

Successfully merging this pull request may close these issues.

ObserveForeignPdoAsync: a caller cutting in between its uploads mixes a live COB-ID with the file's mapping

1 participant