puniverse / quasar

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

Instrumentation verification failure for SAM converted lambdas #275

Closed exFalso closed 7 years ago

exFalso commented 7 years ago

See https://github.com/puniverse/quasar/pull/274/files for a failing test case.

In summary the test declares a Kotlin functional interface and a function that accepts an instance. They are all annotated.

Then this function is called from Java with a lambda. This throws a verification exception.

pron commented 7 years ago

Which Quasar version? Can you attach the trace?

exFalso commented 7 years ago

This happens on master and latest published snapshot (7.8-SNAPSHOT). The (optimized) part looks suspicious

$ gradle quasar-kotlin:test --tests "*KotlinSamInterfaceTest*"
(...)
:quasar-kotlin:test
Running test: Test testSamConvertedLambda(co.paralleluniverse.kotlin.KotlinSamInterfaceTest)
Failed test testSamConvertedLambda [co.paralleluniverse.kotlin.KotlinSamInterfaceTest] with exception: java.util.concurrent.ExecutionException: co.paralleluniverse.fibers.VerifyInstrumentationException: Uninstrumented whole methods ('**') or single calls ('!!') detected: 
    at co.paralleluniverse.common.util.ExtendedStackTrace.here() (ExtendedStackTrace.java:46)
    at co.paralleluniverse.fibers.Fiber.checkInstrumentation() (Fiber.java:1694)
    at co.paralleluniverse.fibers.Fiber.verifySuspend(co.paralleluniverse.fibers.Fiber) (Fiber.java:1667)
    at co.paralleluniverse.fibers.Fiber.verifySuspend() (Fiber.java:1662)
    at co.paralleluniverse.fibers.Fiber.sleep(long,java.util.concurrent.TimeUnit) (Fiber.java:693)
    at co.paralleluniverse.fibers.Fiber.sleep(long) (Fiber.java:685)
    at co.paralleluniverse.strands.Strand.sleep(long) (Strand.java:427)
    at co.paralleluniverse.kotlin.KotlinSamInterfaceTest$1.lambda$run$9ca90355$1() (KotlinSamInterfaceTest.java:19) (optimized)
    at co.paralleluniverse.kotlin.KotlinSamInterfaceKt.accept(co.paralleluniverse.kotlin.KotlinSamInterface) (KotlinSamInterface.kt:17) !! (instrumented suspendable calls at: lines [17],  calls [co.paralleluniverse.kotlin.KotlinSamInterface.doSomething()])
    at co.paralleluniverse.kotlin.KotlinSamInterfaceTest$1.run() (KotlinSamInterfaceTest.java:17)
    at co.paralleluniverse.fibers.Fiber.run1() (Fiber.java:1092)
java.util.concurrent.ExecutionException: co.paralleluniverse.fibers.VerifyInstrumentationException: Uninstrumented whole methods ('**') or single calls ('!!') detected: 
    at co.paralleluniverse.common.util.ExtendedStackTrace.here() (ExtendedStackTrace.java:46)
    at co.paralleluniverse.fibers.Fiber.checkInstrumentation() (Fiber.java:1694)
    at co.paralleluniverse.fibers.Fiber.verifySuspend(co.paralleluniverse.fibers.Fiber) (Fiber.java:1667)
    at co.paralleluniverse.fibers.Fiber.verifySuspend() (Fiber.java:1662)
    at co.paralleluniverse.fibers.Fiber.sleep(long,java.util.concurrent.TimeUnit) (Fiber.java:693)
    at co.paralleluniverse.fibers.Fiber.sleep(long) (Fiber.java:685)
    at co.paralleluniverse.strands.Strand.sleep(long) (Strand.java:427)
    at co.paralleluniverse.kotlin.KotlinSamInterfaceTest$1.lambda$run$9ca90355$1() (KotlinSamInterfaceTest.java:19) (optimized)
    at co.paralleluniverse.kotlin.KotlinSamInterfaceKt.accept(co.paralleluniverse.kotlin.KotlinSamInterface) (KotlinSamInterface.kt:17) !! (instrumented suspendable calls at: lines [17],  calls [co.paralleluniverse.kotlin.KotlinSamInterface.doSomething()])
    at co.paralleluniverse.kotlin.KotlinSamInterfaceTest$1.run() (KotlinSamInterfaceTest.java:17)
    at co.paralleluniverse.fibers.Fiber.run1() (Fiber.java:1092)
    at co.paralleluniverse.fibers.Fiber.get(Fiber.java:1388)
    at co.paralleluniverse.fibers.Fiber.join(Fiber.java:1363)
    at co.paralleluniverse.kotlin.KotlinSamInterfaceTest.testSamConvertedLambda(KotlinSamInterfaceTest.java:26)
    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.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
    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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy3.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109)
    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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:147)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:129)
    at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: co.paralleluniverse.fibers.VerifyInstrumentationException: Uninstrumented whole methods ('**') or single calls ('!!') detected: 
    at co.paralleluniverse.common.util.ExtendedStackTrace.here() (ExtendedStackTrace.java:46)
    at co.paralleluniverse.fibers.Fiber.checkInstrumentation() (Fiber.java:1694)
    at co.paralleluniverse.fibers.Fiber.verifySuspend(co.paralleluniverse.fibers.Fiber) (Fiber.java:1667)
    at co.paralleluniverse.fibers.Fiber.verifySuspend() (Fiber.java:1662)
    at co.paralleluniverse.fibers.Fiber.sleep(long,java.util.concurrent.TimeUnit) (Fiber.java:693)
    at co.paralleluniverse.fibers.Fiber.sleep(long) (Fiber.java:685)
    at co.paralleluniverse.strands.Strand.sleep(long) (Strand.java:427)
    at co.paralleluniverse.kotlin.KotlinSamInterfaceTest$1.lambda$run$9ca90355$1() (KotlinSamInterfaceTest.java:19) (optimized)
    at co.paralleluniverse.kotlin.KotlinSamInterfaceKt.accept(co.paralleluniverse.kotlin.KotlinSamInterface) (KotlinSamInterface.kt:17) !! (instrumented suspendable calls at: lines [17],  calls [co.paralleluniverse.kotlin.KotlinSamInterface.doSomething()])
    at co.paralleluniverse.kotlin.KotlinSamInterfaceTest$1.run() (KotlinSamInterfaceTest.java:17)
    at co.paralleluniverse.fibers.Fiber.run1() (Fiber.java:1092)
    at co.paralleluniverse.fibers.Fiber.checkInstrumentation(Fiber.java:1757)
    at co.paralleluniverse.fibers.Fiber.checkInstrumentation(Fiber.java:1698)
    at co.paralleluniverse.fibers.Fiber.checkInstrumentation(Fiber.java:1694)
    at co.paralleluniverse.fibers.Fiber.verifySuspend(Fiber.java:1667)
    at co.paralleluniverse.fibers.Fiber.verifySuspend(Fiber.java:1662)
    at co.paralleluniverse.fibers.Fiber.sleep(Fiber.java:693)
    at co.paralleluniverse.fibers.Fiber.sleep(Fiber.java:685)
    at co.paralleluniverse.strands.Strand.sleep(Strand.java:427)
    at co.paralleluniverse.kotlin.KotlinSamInterfaceTest$1.lambda$run$9ca90355$1(KotlinSamInterfaceTest.java:19)
    at co.paralleluniverse.kotlin.KotlinSamInterfaceKt.accept(KotlinSamInterface.kt:17)
    at co.paralleluniverse.kotlin.KotlinSamInterfaceTest$1.run(KotlinSamInterfaceTest.java:17)
    at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092)
    at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788)
    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)

co.paralleluniverse.kotlin.KotlinSamInterfaceTest > testSamConvertedLambda FAILED
    java.util.concurrent.ExecutionException at KotlinSamInterfaceTest.java:26
        Caused by: co.paralleluniverse.fibers.VerifyInstrumentationException

1 test completed, 1 failed
:quasar-kotlin:test FAILED
circlespainter commented 7 years ago

This seems to have a similar cause as #279 but it didn't work with BCI-based verification either, seemingly due to BCIs being brittle at times.

pron commented 7 years ago

This happens because the name-based verification fails to verify calls to lambdas, as their method name (bound to the callsite with a bootstrap method), may fail to match the interface's method name. Reproduced in Java:

public class SamInterfaceTest {
    public interface SamInterface {
        void doSomething() throws SuspendExecution;
    }

    static void accept(SamInterface f) throws SuspendExecution {
        f.doSomething();
    }

    public static void main(String[] args) throws Exception {
        new Fiber() {
            @Override
            protected Object run() throws SuspendExecution, InterruptedException {
                accept(() -> {
                    try {
                        Strand.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
                return null;
            }
        }.start().join();
    }
}
circlespainter commented 7 years ago

Yes, I think the root cause here is the same as here https://github.com/puniverse/quasar/issues/279#issuecomment-310848980

pron commented 7 years ago

I've re-enabled the bci-based check in case the name verification fails. This seems to solve this particular problem. Strength in depth... ¯\_(ツ)_/¯