question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

RESTEasy Reactive: Lock contention between callback processing and resume()

See original GitHub issue

Description

I was running some performance tests on Resteasy reactive and picked up some lock contention (about 11% of all contention during my load test) which I think may not be needed:

image image

Its this code here on org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext:

 synchronized void onComplete(Throwable throwable) {
        if (completionCallbacks != null) {
            for (CompletionCallback callback : completionCallbacks) {
                callback.onComplete(throwable);
            }
        }
 }
@Override
    public synchronized void registerCompletionCallback(CompletionCallback callback) {
        if (completionCallbacks == null) {
            completionCallbacks = new ArrayList<>();
        }
        completionCallbacks.add(callback);
    }

I am assuming the onComplete is contending with the resume() calls which also synchronize on the object.

Implementation ideas

In order to resolve this, and as a by-product avoid state issues of callbacks being added after they may have been processed, I suggest using an explicit lock and state flag as opposed to locking on (this):

private final Lock stateManagementLock = new ReentrantLock(); // Prevent race conditions on callbacks without needing to lock on (this)
private boolean completionCallbacksInvoked = false;

void onComplete(Throwable throwable) {
        try {
            stateManagementLock.lock();
            if (completionCallbacks != null) {
                for (CompletionCallback callback : completionCallbacks) {
                    callback.onComplete(throwable);
                }
                completionCallbacks = null;
            }
            completionCallbacksInvoked = true;
        } finally {
            stateManagementLock.unlock();
        }
    }

    @Override
    public void registerCompletionCallback(CompletionCallback callback) {
        try {
            stateManagementLock.lock();
            if (completionCallbacksInvoked) {
                throw new IllegalStateException("Completion callbacks cannot be registered after the context has been closed");
            }
            if (completionCallbacks == null) {
                completionCallbacks = new ArrayList<>();
            }
            completionCallbacks.add(callback);
        } finally {
            stateManagementLock.unlock();
        }
 }

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:20 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
bcluapcommented, Mar 19, 2021

Very reasonable. Cannot see why one would ever go from worker back to eventloop on purpose

On Fri, Mar 19, 2021 at 9:26 AM Georgios Andrianakis < @.***> wrote:

As I am certain that the @NonBlocking -> @Blocking -> @NonBlocking dance will cause problems, here is what I propose:

We do add support for @NonBlocking on filters, but all the @NonBlocking filters must be the first ones to execute - otherwise fail.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/quarkusio/quarkus/issues/15732#issuecomment-802615743, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGMB23KJT6QSKJT77IW6S3TTEL4D3ANCNFSM4ZGZUMYQ .

0reactions
geoandcommented, Mar 19, 2021
Read more comments on GitHub >

github_iconTop Results From Across the Web

RESTEasy Reactive - To block or not to block - Quarkus
You have attempted to perform a blocking operation on a IO thread. This is not allowed, as blocking the IO thread will cause...
Read more >
ResumeCallback (RESTEasy JAX-RS 3.0-beta-1 API)
A resume callback notification method that will be invoked in case the asynchronous response is being resumed by an error (e.g. in case...
Read more >
Chapter 21. Remote API Red Hat JBoss BPM Suite 6.4
Red Hat JBoss BPM Suite provides various ways how to access the execution server in Business Central remotely including REST, JMS, SOAP, and...
Read more >
chore(deps): update dependency io.quarkus:quarkus ... - GitLab
Unit as a return type; #​23503 - Fix param converter processing in Resteasy Reactive ... Reactive: Lock contention between callback processing and resume()...
Read more >
Kogito Documentation - KIE
Kogito is a cloud-native business automation technology for building cloud-ready business applications. The name Kogito derives from the ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found