puniverse / quasar

Fibers, Channels and Actors for the JVM
http://docs.paralleluniverse.co/quasar/
Other
4.56k stars 574 forks source link

FiberAsync.runBlocking interruption should interrupt the executing thread? #245

Closed victornoel closed 7 years ago

victornoel commented 7 years ago

Hi,

When inside a FIber f1, some code is using FiberAsync.runBlocking(), and then I call f1.cancel(true), shouldn't the thread executing the blocking code be interrupted?

Currently I feel like FiberAsync.runBlocking() itself throws an InterruptedException, but its thread is not interrupted…

I tried to adapt one of the quasar unit test for my use case to show in more details what I mean:

    @Test
    public void testCancel1() throws Exception {
        final AtomicBoolean started = new AtomicBoolean();
        final AtomicBoolean terminated = new AtomicBoolean();

        Fiber fiber = new Fiber(new SuspendableRunnable() {
            @Override
            public void run() throws SuspendExecution, InterruptedException {
                FiberAsync.runBlocking(Executors.newSingleThreadExecutor(),
                        new CheckedCallable<Void, RuntimeException>() {
                            @Override
                            public Void call() throws RuntimeException {
                                started.set(true);
                                try {
                                    Thread.sleep(1000);
                                    fail("InterruptedException not thrown");
                                } catch (InterruptedException e) {
                                }
                                terminated.set(true);
                                return null;
                            }
                        });
            }
        });

        fiber.start();
        Thread.sleep(100);
        fiber.cancel(true);
        fiber.join(5, TimeUnit.MILLISECONDS);
        assertThat(started.get(), is(true));
        assertThat(terminated.get(), is(true));
    }

Currently, it gives me the following error:

java.util.concurrent.ExecutionException: java.lang.InterruptedException
    at co.paralleluniverse.fibers.Fiber.get(Fiber.java:1372)
    at co.paralleluniverse.fibers.Fiber.join(Fiber.java:1343)
    at org.ow2.petals.cockpit.server.QuasarTest.testCancel1(QuasarTest.java:49)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.InterruptedException
    at co.paralleluniverse.fibers.FiberAsync.run(FiberAsync.java:142)
    at co.paralleluniverse.fibers.FiberAsync.runBlocking(FiberAsync.java:409)
    at org.ow2.petals.cockpit.server.QuasarTest$1.run(QuasarTest.java:29)
    at co.paralleluniverse.strands.SuspendableUtils$VoidSuspendableCallable.run(SuspendableUtils.java:44)
    at co.paralleluniverse.strands.SuspendableUtils$VoidSuspendableCallable.run(SuspendableUtils.java:32)
    at co.paralleluniverse.fibers.Fiber.run(Fiber.java:1072)
    at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1067)
    at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:767)
    at co.paralleluniverse.fibers.FiberForkJoinScheduler$FiberForkJoinTask.exec1(FiberForkJoinScheduler.java:266)
    at co.paralleluniverse.concurrent.forkjoin.ParkableForkJoinTask.doExec(ParkableForkJoinTask.java:117)
    at co.paralleluniverse.concurrent.forkjoin.ParkableForkJoinTask.exec(ParkableForkJoinTask.java:74)
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
pron commented 7 years ago

I think this is a reasonable suggestion, and a simple one, too. I'll implement it soon.

victornoel commented 7 years ago

@pron is there any news on that? Can I offer some help? I'm ok to make a PR but maybe I will need some tips on how to approach the problem :)

pron commented 7 years ago

Oh, sorry; forgot about this. I will try to commit something today.

pron commented 7 years ago

In SNAPSHOT

victornoel commented 7 years ago

Excellent, thanks @pron, I will play with it next week and report back in case of problem :)