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

CompletableFuture with timeout hangs Isolate #4024

Closed
alexfedorenchik opened this issue Nov 16, 2021 · 2 comments
Closed

CompletableFuture with timeout hangs Isolate #4024

alexfedorenchik opened this issue Nov 16, 2021 · 2 comments
Assignees

Comments

@alexfedorenchik
Copy link

Describe the issue
java.util.concurrent.CompletableFuture$Delayer class that is used in "orTimeout" and "completeOnTimeout" methods prevents isolate from being teared-down.

As far as I understand, Delayer instantiates a static ScheduledThreadPoolExecutor with a single daemon thread that is not terminated due to #2617 (comment)

Issue can be workarounded by shutting down that executor using reflection, but perhaps it makes sense to provide some generic substitution?

Steps to reproduce the issue
Example source (Test.java)

import java.lang.reflect.Method;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.Isolates;
import org.graalvm.nativeimage.Isolates.CreateIsolateParameters;
import org.graalvm.nativeimage.c.function.CEntryPoint;

public class Test {
    public static void main(String[] args) {
        IsolateThread ctx = Isolates.createIsolate(CreateIsolateParameters.getDefault());
        System.out.println("Isolate created");
        run(ctx);
        System.out.println("Isolate completed");
        Isolates.tearDownIsolate(ctx);
        System.out.println("Isolate cleared");
    }

    @CEntryPoint
    public static void run(@CEntryPoint.IsolateThreadContext IsolateThread ctx) {
        var exec = Executors.newFixedThreadPool(1);
        CompletableFuture
                .supplyAsync(() -> "Some work is done", exec)
                .whenComplete((result, throwable) -> System.out.println(result))
                .orTimeout(1, TimeUnit.SECONDS)
                .join();
        exec.shutdownNow();
        //Uncomment next line for applying workaround
        //shutdownNowDelayScheduler();
    }

    private static void shutdownNowDelayScheduler() {
        try {
            var delayerClass = Class.forName("java.util.concurrent.CompletableFuture$Delayer");
            var delayerField = delayerClass.getDeclaredField("delayer");
            delayerField.setAccessible(true);
            var delayerValue = delayerField.get(null);
            Method method = ExecutorService.class.getDeclaredMethod("shutdownNow", new Class[]{});
            method.invoke(delayerValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Build:

echo "Main-Class: Test" > manifest.txt && javac Test.java &&  jar -cvfm Test.jar manifest.txt Test.class && native-image -jar Test.jar

Run native-image:

./Test

Expected Result:

Isolate created
Some work is done
Isolate completed
Isolate cleared

app finished

Actual Result:

Isolate created
Some work is done
Isolate completed

app hangs...

Describe GraalVM and your environment:

  • GraalVM version CE 21.2.0
  • JDK major version: 11
  • OS: macOS Monterey 12.0.1
  • Architecture: x86
@oubidar-Abderrahim
Copy link
Member

Thank you for reporting this, we will take a look into it and get back to you.

@oubidar-Abderrahim oubidar-Abderrahim self-assigned this Nov 19, 2021
@peter-hofer
Copy link
Member

Fixed in 52b709f.

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

No branches or pull requests

3 participants