Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deadlock while calling write-locked method from another write-locked method in multiple threads #35345

Closed
timonzi opened this issue Aug 14, 2023 · 3 comments · Fixed by #35370
Labels
area/arc Issue related to ARC (dependency injection) kind/bug Something isn't working
Milestone

Comments

@timonzi
Copy link

timonzi commented Aug 14, 2023

Describe the bug

We have a constellation where we call a write-locked method of a bean in multiple threads. This method calls another method within the same bean, which is also write-locked. With Quarkus 3.2.4.Final we get now a deadlock. With Quarkus 3.2.3.Final it worked fine.

Code from reproducer:

@QuarkusTest
class LockTest {

    private final ExecutorService threadPool = Executors.newCachedThreadPool();

    @Inject
    LockBean lockBean;

    @Test
    void testLocks() throws ExecutionException, InterruptedException {
        final var futures = new ArrayList<Future<String>>();
        for (int i = 0; i < 10; i++) {
            final Future<String> submit = threadPool.submit(() -> {
                lockBean.method1();
                return "value";
            });
            futures.add(submit);
        }

        for (final var future : futures) {
            future.get();
        }

    }

}
@ApplicationScoped
@Lock
public class LockBean {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    public void method1() {
        logger.info("execute method1");
        method2();
    }

    public void method2() {
        logger.info("execute method2");
    }
}

This is probably related to #35136

Hint: I didn't wrote the code in our application and didn't worked with locks a lot. So I'm not sure whether my problem is expected, but I can see the problem occurs after the version switch.

Expected behavior

No deadlock

Actual behavior

The first method is called and then I get a deadlock.

How to Reproduce?

Reproducer: https://github.com/timonzi/lock-problem

  1. Execute test --> Deadlock
  2. Change version to 3.2.3.Final
  3. Execute test --> works fine

Output of uname -a or ver

Linux nb-timonzi 6.2.0-26-generic #26~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Jul 13 16:27:29 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

Output of java -version

openjdk version "17.0.6" 2023-01-17

GraalVM version (if different from Java)

No response

Quarkus version or git rev

3.2.4.Final

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.9.1

Additional information

No response

@timonzi timonzi added the kind/bug Something isn't working label Aug 14, 2023
@yrodiere yrodiere added area/arc Issue related to ARC (dependency injection) and removed triage/needs-triage labels Aug 16, 2023
@quarkus-bot
Copy link

quarkus-bot bot commented Aug 16, 2023

/cc @Ladicek (arc), @manovotn (arc), @mkouba (arc)

@manovotn
Copy link
Contributor

manovotn commented Aug 16, 2023

You're correct, this is linked to #35136
Seems to be caused by the fact that we always lock the ReentrantLock on any write and only release it once the method has been executed. In this scenario, a thread A can acquire the write lock on ReentrantReadWriteLock while thread B manages to get lock on ReentrantLock

@manovotn
Copy link
Contributor

Perhaps we could only use the ReentrantLock in case we detect existing read lock (the purpose of this lock is to prevent this scenario anyway).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/arc Issue related to ARC (dependency injection) kind/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants