airbnb / epoxy

Epoxy is an Android library for building complex screens in a RecyclerView
https://goo.gl/eIK82p
Apache License 2.0
8.5k stars 733 forks source link

Infinite loop in Annotation Processor? #443

Closed alexbchr closed 6 years ago

alexbchr commented 6 years ago

Hi,

I use the Carousel feature in Epoxy in one of my RecyclerView. Since I wanted to extend it with multiple features, I decided to extend the Carousel class.

@ModelView(autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT)
class NonSnappingCarousel(context: Context) : Carousel(context) {
    // Some ModelProp properties
}

This example works fine. However, since I began having more features in that extended Carousel class, I decided to write myself a BaseCarousel class, containing many of features that other carousel subclasses could need.

I therefore decided to rewrite the exact same code as such, only moving @ModelProp properties from one file to the other:

@ModelView(autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT)
open class BaseCarousel(context: Context) : Carousel(context) {
    // Some moved ModelProp properties
}

class NonSnappingCarousel(context: Context) : BaseCarousel(context) {
    // Some non-moved ModelProp properties
}

However, the above code fails to compile without any build error. Gradle gets stuck at 7% at kaptAlphaDebugKotlin. And what is even weirder is that once I try to build that code, even if I revert my changes, Gradle would get stuck at this exact same place. To fix this, I need to kill the gradle java process running in background. After that, I'm able to build my project again, except when I bring back the specific changes mentioned above.

I tried and encountered this issue with Gradle 4.4 up to 4.8 (released this morning).

Edit:

Here is a basic example that reproduce the issue in a brand new Android project:

package com.example.test.myapplication

import android.content.Context
import android.util.AttributeSet
import com.airbnb.epoxy.Carousel
import com.airbnb.epoxy.ModelView
import com.airbnb.epoxy.TextProp

@ModelView(autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT)
open class BaseCarousel : Carousel {

    var propertyOne: CharSequence? = null
        @TextProp set

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle)
}

// If you remove this class declaration, everything compiles correctly
@ModelView(autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT)
class NonSnappingCarousel : BaseCarousel {

    var propertyTwo: CharSequence? = null
        @TextProp set

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle)
}
elihart commented 6 years ago

Thanks for reporting, definitely sounds like an issue in the annotation processor.

This reminds me of https://github.com/airbnb/epoxy/issues/427

Can you post your full code?

alexbchr commented 6 years ago

I didn't see #427 before opening this issue but yes when I run the build with the --debug flag I get a similar output as in this other issue.

I updated the current issue with a minimal code example that reproduces the issue.

elihart commented 6 years ago

Thanks. Are you also able to get the Thread Dump of the KotlinCompileDaemon, like the other issue posted? that stack trace would be very valuable

alexbchr commented 6 years ago

Here is the end of the output I get when executing a ./gradlew clean build --debug command:

08:16:01.085 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry.
08:16:01.085 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
08:16:01.085 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
08:16:01.086 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry.
08:16:01.086 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
08:16:01.086 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
08:16:05.784 [DEBUG] [org.gradle.process.internal.health.memory.MemoryManager] Emitting OS memory status event {Total: 8589934592, Free: 1654726656}
08:16:05.785 [DEBUG] [org.gradle.launcher.daemon.server.health.LowMemoryDaemonExpirationStrategy] Received memory status update: {Total: 8589934592, Free: 1654726656}
08:16:05.785 [DEBUG] [org.gradle.process.internal.health.memory.MemoryManager] Emitting JVM memory status event {Maximum: 1431830528, Committed: 471334912}
08:16:10.787 [DEBUG] [org.gradle.process.internal.health.memory.MemoryManager] Emitting OS memory status event {Total: 8589934592, Free: 1734369280}
08:16:10.787 [DEBUG] [org.gradle.launcher.daemon.server.health.LowMemoryDaemonExpirationStrategy] Received memory status update: {Total: 8589934592, Free: 1734369280}
08:16:10.787 [DEBUG] [org.gradle.process.internal.health.memory.MemoryManager] Emitting JVM memory status event {Maximum: 1431830528, Committed: 471334912}
08:16:11.085 [DEBUG] [org.gradle.launcher.daemon.server.Daemon] DaemonExpirationPeriodicCheck running
08:16:11.086 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry.
08:16:11.086 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
08:16:11.087 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
08:16:11.089 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry.
08:16:11.089 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
08:16:11.089 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.

It looks a lot like the output in #427.

And here is the thread dump from the KotlinCompileDaemon:

"RMI TCP Connection(3)-127.0.0.1" #20 daemon prio=5 os_prio=31 tid=0x00007fcec14c9000 nid=0x1207 runnable [0x0000700010143000]
   java.lang.Thread.State: RUNNABLE
    at com.sun.tools.javac.code.Symbol$TypeSymbol.getEnclosedElements(Symbol.java:734)
    at com.airbnb.epoxy.ViewAttributeInfo.assignDefaultValue(ViewAttributeInfo.kt:213)
    at com.airbnb.epoxy.ViewAttributeInfo.<init>(ViewAttributeInfo.kt:109)
    at com.airbnb.epoxy.ModelViewInfo.addPropIfNotExists(ModelViewInfo.kt:173)
    at com.airbnb.epoxy.ModelViewProcessor$updateViewsForInheritedViewAnnotations$1$2.invoke(ModelViewProcessor.kt:311)
    at com.airbnb.epoxy.ModelViewProcessor$updateViewsForInheritedViewAnnotations$1$2.invoke(ModelViewProcessor.kt:12)
    at com.airbnb.epoxy.ModelViewProcessor$updateViewsForInheritedViewAnnotations$1$1.invoke(ModelViewProcessor.kt:298)
    at com.airbnb.epoxy.ModelViewProcessor$updateViewsForInheritedViewAnnotations$1.invoke(ModelViewProcessor.kt:306)
    at com.airbnb.epoxy.ModelViewProcessor$updateViewsForInheritedViewAnnotations$1.invoke(ModelViewProcessor.kt:12)
    at com.airbnb.epoxy.KotlinUtilsKt$iterateSuperClasses$1.invoke(KotlinUtils.kt:146)
    at com.airbnb.epoxy.KotlinUtilsKt$iterateSuperClasses$1.invoke(KotlinUtils.kt)
    at com.airbnb.epoxy.KotlinUtilsKt.iterateClassHierarchy(KotlinUtils.kt:132)
    at com.airbnb.epoxy.KotlinUtilsKt.iterateSuperClasses(KotlinUtils.kt:143)
    at com.airbnb.epoxy.ModelViewProcessor.updateViewsForInheritedViewAnnotations(ModelViewProcessor.kt:281)
    at com.airbnb.epoxy.ModelViewProcessor.process(ModelViewProcessor.kt:40)
    at com.airbnb.epoxy.EpoxyProcessor.processRound(EpoxyProcessor.java:193)
    at com.airbnb.epoxy.EpoxyProcessor.process(EpoxyProcessor.java:165)
    at org.jetbrains.kotlin.kapt3.ProcessorWrapper.process(annotationProcessing.kt:131)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
    at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
    at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1068)
    at org.jetbrains.kotlin.kapt3.AnnotationProcessingKt.doAnnotationProcessing(annotationProcessing.kt:87)
    at org.jetbrains.kotlin.kapt3.AnnotationProcessingKt.doAnnotationProcessing$default(annotationProcessing.kt:45)
    at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.runAnnotationProcessing(Kapt3Extension.kt:257)
    at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:212)
    at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:95)
    at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM$analyzeFilesWithJavaIntegration$2.invoke(TopDownAnalyzerFacadeForJVM.kt:97)
    at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:107)
    at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:84)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:374)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:64)
    at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:101)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:365)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:130)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:161)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:63)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:107)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:51)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:96)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$1$2.invoke(CompileServiceImpl.kt:405)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$1$2.invoke(CompileServiceImpl.kt:98)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:920)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:98)
    at org.jetbrains.kotlin.daemon.common.DummyProfiler.withMeasure(PerfUtils.kt:137)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.checkedCompile(CompileServiceImpl.kt:950)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.doCompile(CompileServiceImpl.kt:919)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:404)
    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 sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$6/962591831.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
    - <0x000000076252a138> (a java.util.concurrent.ThreadPoolExecutor$Worker)
elihart commented 6 years ago

Thanks a lot! I'm still traveling for the next week, but I'll fix it after that

elihart commented 6 years ago

Fixed with https://github.com/airbnb/epoxy/pull/447