He-Pin opened a new issue, #3739:
URL: https://github.com/apache/pekko/issues/3739

   ### Motivation
   
   Recent work hardened cancellation behaviour on the plaintext-output side of 
the TLS operators (#3727, #3731, #3738). While auditing cancellation symmetry 
across the TLS stage's four teardown paths, I found a gap in the opposite 
direction: when the transport (ciphertext) output is cancelled while inbound 
records have already been received but not yet decrypted, both TLS engines 
discard that data silently.
   
   The other three teardown paths all have an observable contract:
   
   - transport input truncated without `close_notify`: received data is 
delivered and `SessionTruncated` is emitted (documented, covered by `TlsSpec`);
   - transport input failure: the stage fails via `failTls`, visible to the 
application;
   - plaintext output cancellation: the graph-stage engine drains accepted 
plaintext (#3727, #3731, #3738), documented in the stream IO guide.
   
   Only "transport output cancelled while inbound data awaits plaintext demand" 
ends in a clean `onComplete` with the received data dropped and no signal at 
all.
   
   ### Scenario
   
   Observed on `main` (2.0.0-M4+ snapshot), both 
`pekko.stream.materializer.tls.engine = legacy-actor` and `graph-stage`.
   
   1. A TLS client stage with an established session. The peer sends an 
application data record (e.g. a final response); the client's transport input 
receives the ciphertext.
   2. The client's plaintext output has no outstanding demand at that moment 
(the consumer has not requested yet).
   3. The transport output is then cancelled while the read side stays healthy 
(e.g. a kill switch on the send path, or an application that deliberately stops 
sending but still expects to read the response).
   
   ### Observed
   
   - The stage completes immediately; the plaintext output receives 
`onComplete` with no `SessionBytes`.
   - The already-received record is dropped undecrypted, and no 
`SessionTruncated` is emitted, so the application cannot tell that data 
received at the record layer was thrown away.
   - Identical behaviour with both engines.
   - If plaintext demand existed before the cancellation, the data is delivered 
normally, so the loss is specific to "cancellation while inbound data awaits 
demand".
   
   ### Internal notes
   
   - Graph stage: inbound decryption is gated on plaintext-output demand 
(`inboundReady` requires `userOutput.isDemandAvailable` in `TlsGraphStage`). A 
cancelled transport output makes `outboundCompleted` (and thus 
`bidirectionalCompleted`) true immediately, so the pump skips every phase and 
reaches `pumpFinished`, which cancels the transport input queue — the inbound 
close path never runs, hence no `closeInbound`, no `SessionTruncated`.
   - Legacy actor: same demand gating in the inbound transfer state 
(`demandAvailableFor(UserOut)`); a cancelled transport output jumps straight to 
the completed phase (`TLSActor.doOutbound`).
   
   ### Expected
   
   Either of the following, plus a sentence in the stream IO guide (the current 
text only covers the plaintext-output-cancellation/drain direction):
   
   1. Deliver already-received inbound records to the plaintext output as 
demand arrives before completing — the read side is independent of the 
cancelled write side; or
   2. At minimum, run the inbound close path so `SessionTruncated` is emitted 
before completion, making the loss observable.
   
   Option 2 is a small, low-risk change (signal only, no completion-timing 
change). Option 1 mirrors the outbound drain philosophy but needs a decision on 
how long the stage may wait for plaintext demand, similar to the trade-off 
already accepted and documented for the outbound drain.
   
   ### References
   
   Refs #3727, #3731, #3738


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to