The HttpBodySubscriberWrapper is a class that ensures that a subscriber will be 
subscribed to before it is completed. It also provides hooks to its two 
subclasses (one for HTTP/1, one for HTTP/2) that allows subclasses to register 
the susbscriber with the HttpClient at subscription time, and to unregister it 
when it is eventualy completed, or when the subscription is cancelled.

There is however a race condition that can happen when a subscription is 
cancelled: it can happen that unregister is called before register. The 
CancelRequestTest has been observed failing once or twice on personal jobs. 
Though the particular mechanics of this race is hard to understand, the logs of 
the tests have brought sufficient evidence that this is what was happening. 

The symptom is finding one subscriber still registered after completion of the 
exchange:

test 
CancelRequestTest.testGetSendAsync("https://localhost:42711/https1/x/same/interrupt";,
 true, true): failure
java.lang.AssertionError: WARNING: tracker for HttpClientImpl(13) has 
outstanding operations:
Pending HTTP Requests: 0
Pending HTTP/1.1 operations: 0
Pending HTTP/2 streams: 0
Pending WebSocket operations: 0
Pending TCP connections: 0
Pending Subscribers: 1
Total pending operations: 0
Facade referenced: true
Selector alive: true

The proposed fix hoist special hooks for register/unregister in the superclass, 
merges all various volatile boolean states into a single int state, and protect 
the state changes  to subscribed/register/unregister by the same subscription 
lock.
If cancelling the subscription happens at around the same time that the 
subscriber is subscribed this ensures that the subscriber won't be removed from 
the map before it is added.

-------------

Commit messages:
 - 8302635

Changes: https://git.openjdk.org/jdk/pull/12587/files
 Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=12587&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8302635
  Stats: 233 lines in 4 files changed: 190 ins; 22 del; 21 mod
  Patch: https://git.openjdk.org/jdk/pull/12587.diff
  Fetch: git fetch https://git.openjdk.org/jdk pull/12587/head:pull/12587

PR: https://git.openjdk.org/jdk/pull/12587

Reply via email to