RFR: JDK-8288746: HttpClient resources could be reclaimed more eagerly
Daniel Fuchs
dfuchs at openjdk.org
Mon Jun 27 12:13:38 UTC 2022
On Sun, 26 Jun 2022 06:08:07 GMT, Jaikiran Pai <jpai at openjdk.org> wrote:
>> Hi,
>>
>> Please find here a patch that should help the HttpClient's SelectorManager thread to terminate more timely, allowing the resources consumed by the client to be released earlier.
>>
>> The idea is to use a Cleaner registered with the HttpClientFacade to wakeup the Selector when the facade is being gc'ed.
>> Some tests have been modified to wait for the selector manager thread to shutdown, and some of them have been observed to timeout when the fix is not in place.
>
> Hello Daniel, the source code changes look OK to me. The test code changes I haven't finished reviewing yet. A few questions related to the `SelectorManager`:
>
> I realize that the goal of this change is to wakeup the `SelectorManager` from its select operation so that it can then go ahead and exit from its `run()` and in the process shut itself down.
>
> In the `SelectorManager`, I see that when it is potentially woken up, it checks if the `HttpClientImpl` (via its facade) is still referenced and if not, it will trigger the shutdown. That happens here https://urldefense.com/v3/__https://github.com/openjdk/jdk/blob/master/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java*L1240__;Iw!!ACWV5N9M2RV99hQ!JL9hqB4ORwRVy6IHKdvtBmdyVOqqyxumiBnrW7bOxTAJzd_Cjew0bUQwyIgLhB3Q5r4JFXtMG1MXI3ZqfohFozk$ . However, that check is only done if the `select` operation (which was potentially woken up) returns `0` as the number of ready ops. The `Selector.wakeup()` javadoc notes that it's possible that when the selector is woken up, the select operation may return a non-zero value. With the change in this PR where the `HttpClientImpl` has realized that the facade is no longer in use and thus has triggered the `wakeup`, do you think we should shutdown the `SelectorManager` irrespective of what the return value of the `select` operation was? In other words, should that `if (!owner.isReferenced()) {` check in the `SelectorManager` be outside of the `if (n == 0) {` block?
>
> Continuing further, if we do decide that the code in the `SelectorManager` is fine in its current form, do you think we should have an additional `if (!owner.isReferenced()) {` check right at the start of each loop iteration too, something like:
>
> while (!Thread.currentThread().isInterrupted() && !closed) {
> // Check whether client is still alive, and if not,
> // gracefully stop this thread
> if (!owner.isReferenced()) {
> Log.logTrace("{0}: {1}",
> getName(),
> "HttpClient no longer referenced. Exiting...");
> return;
> }
> synchronized (this) {
> ...
>
>
> }
>
> because in its current form, as far as I can see, even if we wakeup the selector eagerly, it's possible that the `select` operation that it was waiting on, might return a non-zero value and we then end up back in that while loop and do another `select` which could then end up waiting for some more seconds (3 seconds by default).
@jaikiran there is already an escape hatch at line 1196:
https://urldefense.com/v3/__https://github.com/openjdk/jdk/blob/7905788e969727c81eea4397f0d9b918cdb5286a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java*L1196__;Iw!!ACWV5N9M2RV99hQ!JL9hqB4ORwRVy6IHKdvtBmdyVOqqyxumiBnrW7bOxTAJzd_Cjew0bUQwyIgLhB3Q5r4JFXtMG1MXI3ZqATA6QVk$
So we will re-check `isReferenced()` again before calling select. I believe we are fine and there's no need to change anything here.
-------------
PR: https://git.openjdk.org/jdk/pull/9217
More information about the core-libs-dev
mailing list