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

atMost not respected if blocking method used in until #225

Open
bencvdb opened this issue Dec 10, 2021 · 1 comment
Open

atMost not respected if blocking method used in until #225

bencvdb opened this issue Dec 10, 2021 · 1 comment

Comments

@bencvdb
Copy link

bencvdb commented Dec 10, 2021

You can run this code to replicate the issue:

import org.awaitility.Awaitility;
import java.time.Duration;
import java.util.Scanner;

public class Test {

    public static void main(String[] args) {
        new Test().test();
    }

    public void test() {
        Scanner in = new Scanner(System.in);
        Awaitility.await().pollDelay(Duration.ZERO).atMost(Duration.ofNanos(1)).until(in::hasNextLine);

        if (in.hasNextLine()) {
            String query = in.nextLine();
            System.out.print("recieved: " + query);
        }
    }
}

Expected behavior: ConditionTimeoutException thrown "immediately"
Actual behavior: Code hangs until a value is entered via stdin.

Suspected issue:
It looks like there is a bug in org.awaitility.core.Uninterruptibles#shutdownUninterruptibly:

static void shutdownUninterruptibly(ExecutorService executor, long timeout, TimeUnit unit) {
boolean interrupted = false;
try {
long remainingNanos = unit.toNanos(timeout);
long end = System.nanoTime() + remainingNanos;
executor.shutdown();
while (true) {
try {
if (!executor.awaitTermination(remainingNanos, unit)) {
executor.shutdownNow();
}
break;
} catch (InterruptedException e) {
interrupted = true;
remainingNanos = end - System.nanoTime();
executor.shutdownNow();
}
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}

The method attempts to shutdown the executor running the until condition. In this case, it is being called here:

return new EvaluationCleanup(executor -> shutdownUninterruptibly(executor, 1, TimeUnit.SECONDS), ExecutorService::shutdownNow);

Consequently it waits for 10^9 seconds instead of 1 second.

The fix is to edit the condition in line:

if (!executor.awaitTermination(remainingNanos, unit)) {

to be:

!executor.awaitTermination(remainingNanos, NANOSECONDS)
@TheNitek
Copy link

TheNitek commented Mar 4, 2022

I created a PR: #234

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants