Problem
send_matching_symbols_request records the request as pending whether or not it was sent, and nothing ever times it out.
src/engine/hot_loop/ccp.rs:1586:
if let Some(conn) = ccp_conn.as_mut() {
...
let _ = conn.send_fix(&[ ... ]);
hb.last_ccp_sent = Instant::now();
log::info!("Sent matching symbols request: req_id={} pattern='{}'", req_id, pattern);
}
self.pending_matching_symbols.push(req_id);
Two ways the entry outlives the request. The send error is discarded, so a failed write still records a pending id. And the push is outside the if let, so a request issued while the CCP transport is down is recorded without any send being attempted at all — the log line that would say otherwise is inside the block.
pending_matching_symbols is only ever drained by a matching response (ccp.rs:362-379). There is no deadline on it, unlike pending_historical, which carries Instant::now() + HISTORICAL_IDLE_TIMEOUT. Reconnect neither resends nor rejects the entry.
Impact
The caller waits forever: no response, no timeout, no error callback. The stale id also stays in the list, and the response matcher falls back to position 0 when a reply carries no echoed request id (ccp.rs:365), so a later request's response can be delivered against the abandoned entry.
Solution
Record the request only where it was actually sent, and give it a deadline the way historical requests have one, so a request that goes out and is never answered terminates rather than hanging. A request issued with no connection should be rejected to the caller at the point of issue.
Notes
Read from v0.7.1 (9367845). Verifiable offline: the send result is discarded at ccp.rs:1590, the push is unconditional at ccp.rs:1600, and grep -rn pending_matching_symbols src/ shows no timeout sweep.
Problem
send_matching_symbols_requestrecords the request as pending whether or not it was sent, and nothing ever times it out.src/engine/hot_loop/ccp.rs:1586:Two ways the entry outlives the request. The send error is discarded, so a failed write still records a pending id. And the push is outside the
if let, so a request issued while the CCP transport is down is recorded without any send being attempted at all — the log line that would say otherwise is inside the block.pending_matching_symbolsis only ever drained by a matching response (ccp.rs:362-379). There is no deadline on it, unlikepending_historical, which carriesInstant::now() + HISTORICAL_IDLE_TIMEOUT. Reconnect neither resends nor rejects the entry.Impact
The caller waits forever: no response, no timeout, no error callback. The stale id also stays in the list, and the response matcher falls back to position 0 when a reply carries no echoed request id (
ccp.rs:365), so a later request's response can be delivered against the abandoned entry.Solution
Record the request only where it was actually sent, and give it a deadline the way historical requests have one, so a request that goes out and is never answered terminates rather than hanging. A request issued with no connection should be rejected to the caller at the point of issue.
Notes
Read from v0.7.1 (9367845). Verifiable offline: the send result is discarded at
ccp.rs:1590, the push is unconditional atccp.rs:1600, andgrep -rn pending_matching_symbols src/shows no timeout sweep.