Open
Description
Environment
- 10x RTU devices → RS485 → USR-RD302 TCP converter → tokio-modbus (TCP)
- Library version: tokio-modbus (latest)
- OS: (e.g., Linux)
Problem
When a Modbus request times out due to device unavailability, subsequent requests using the same context fail with mismatching headers
errors when delayed responses arrive.
Error example:
Err: mismatching headers: expected/request = Header { transaction_id: 97, unit_id: 2 }, actual/response = Header { transaction_id: 95, unit_id: 2 } Ok(ReadHoldingRegisters([17166, 45875, 17162, 45875, 17158, 13107, 17267, 45875, 17260, 19661, 17263, 52429, 16925, 39322, 16965, 28836, 16840, 62915, 16373, 49807, 49300, 48234, 49344, 41943, 49131, 34079, 49480, 8389, 16451, 38273, 49060, 23069, 48881, 43516, 16294, 26214, 16563, 63439, 16603, 8913, 16471, 36176, 16765, 28836, 48979, 29884, 48993, 1573, 48907, 50856, 48969, 64487, 17008, 7864, 17357, 15729, 17506, 34079, 17367, 7864, 17303, 41943, 17632, 15401, 17572, 37356, 50167, 52429, 17463, 24904, 17149, 60293, 17216, 47186, 17261, 28836]))
Reproduction Steps
- Shared context used for multiple devices
- Device responds with high latency
- Timeout triggers correctly
- New request uses same context
- Old delayed response arrives → header mismatch
Current Implementation
let mut locked_ctx = ctx.lock().await; // pegando lock mutável assíncrono
locked_ctx.set_slave(tokio_modbus::Slave(self.id));
let reg = tokio::time::timeout(
timeout,
async {
let result = locked_ctx.read_holding_registers(6, 76).await;
result
}
).await;
Need a way to discard pending responses after timeout when reusing contexts. Suggested solutions:
1. Context reset method: ctx.reset() (clears buffers/transaction state)
2. Automatic response discard on timeout
3. Transaction ID invalidation API
Metadata
Metadata
Assignees
Labels
No labels