jon-valliere commented on PR #77:
URL: https://github.com/apache/mina/pull/77#issuecomment-6062446439

   I had Claude look into it and provided some background.
   
   **Root cause / history**
   
   The `synchronized (queue)` blocks around the drain loops were part of the 
original G1 design. From the description of #44:
   
   > The code which pulls objects out of this Queue is blocked by itself so no 
two threads can be pulling from the Queue concurrently.
   
   They were commented out in 62643fece ("alright lets remove all the 
synchronization from the queue flushes"). That was an experiment on the 
in-progress `bugfix/DIRMINA-1173` branch. I never meant it to be merged. The 
branch was later merged into `2.2.X` together with unrelated maintenance work, 
so the experiment shipped in 2.2.4. This PR restores the intended design.
   
   **Why `mWriteQueue` is the one that matters**
   
   Encryption happens under the handler monitor, so records go into 
`mWriteQueue` in the correct order. The drain runs after the monitor is 
released, though, and it's reached from several threads at once:
   - the application thread: `write()` → `forward_writes`
   - the IO processor thread: `ack()` → `flush_start` (which encrypts more 
queued chunks because of `MAX_UNACK_MESSAGES`) → `forward_writes`
   - the receive path: `receive()` → `forward_writes`
   
   If two threads poll consecutive records and reach `filterWrite` in the 
opposite order, the records go out of order on the wire. TLS sequence numbers 
are implicit, so the peer fails with `bad_record_mac` or corrupted data. Large 
messages split into several records make this much more likely. That fits 
@elecharny's observation that locking `mWriteQueue` alone makes the test pass.
   
   `mReceiveQueue` needs the same protection. `receive()` normally runs on one 
IO thread per session, but a thread-dispatching filter can be placed in front 
of `SslFilter`. Decryption in `receive_start` is serialized by the handler 
monitor, but `forward_received` drains after that monitor is released. Without 
the lock, one thread can still be delivering its decrypted buffers while 
another decrypts the next message and drains too, and the application receives 
the plaintext out of order. `mEventQueue` is exposed the same way. All three 
locks belong to the original design and should stay.
   
   **Requested changes**
   
   1. **Debug logging:** please drop the new entry logs in `forward_*()`. They 
add 2–3 lines per event and don't say much. The existing per-item logs are 
enough.
   2. **`SslFilterTest`:**
      - The 61000–80000 loop is ~19k round trips, which is too slow for the 
regular build. A handful of sizes around the record/packet boundaries should be 
enough.
      - `CompareFilter` only logs on a data mismatch and then counts down the 
latch, so corrupted data doesn't fail the test. Please record it as a failure 
(e.g. set `failure`) so the assertion catches it.
      - Progress is logged at `ERROR` level; please use `DEBUG`.
      - Missing newline at end of file.
   3. **`SslEnd2EndTest`** is bidirectional and asserts the content, which 
covers what was asked for earlier. If it reproduces the failure reliably 
without the fix, I'd be fine keeping only this one.
   
   +1 on the fix itself once the tests are cleaned up.


-- 
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