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

[epilogue] Sporadic runtime errors #7103

Closed
BR88C opened this issue Sep 20, 2024 · 4 comments · Fixed by wpilibsuite/GradleRIO#759
Closed

[epilogue] Sporadic runtime errors #7103

BR88C opened this issue Sep 20, 2024 · 4 comments · Fixed by wpilibsuite/GradleRIO#759
Labels
component: epilogue Annotation-based logging library type: bug Something isn't working.

Comments

@BR88C
Copy link
Contributor

BR88C commented Sep 20, 2024

Generated Epilogue logging classes unpredictably throw runtime errors.

Project setup

Robot.java
@Logged
public final class Robot extends TimedRobot {
  private final ExampleSubsystem exampleSubsystem;
  
  public Robot() {
    exampleSubsystem = new ExampleSubsystem();
  }

  @Override
  public void robotPeriodic() {
    Epilogue.update(this);
  }
}
ExampleSubsystem.java
@Logged
public class ExampleSubsystem extends SubsystemBase {
  private int foo = 0;
  
  public void setFoo(int newFoo) {
    foo = newFoo;
  }

  public int getFoo() {
    return foo;
  }
}
robot/
  subsystems/
    ExampleSubsystem.java
  Main.java
  Robot.java

This example when run in simulation typically throws an error at startup.

Error at org.team340.robot.RobotLogger.update(RobotLogger.java:32): Unhandled exception: java.lang.Error: Unresolved compilation problem: 
        exampleSubsystemLogger cannot be resolved or is not a field

        at org.team340.robot.RobotLogger.update(RobotLogger.java:32)
        at org.team340.robot.RobotLogger.update(RobotLogger.java:1)
        at edu.wpi.first.epilogue.logging.ClassSpecificLogger.tryUpdate(ClassSpecificLogger.java:64)
        at edu.wpi.first.epilogue.Epilogue.update(Epilogue.java:35)
        at org.team340.robot.Robot.robotPeriodic(Robot.java:70)
        at edu.wpi.first.wpilibj.IterativeRobotBase.loopFunc(IterativeRobotBase.java:400)
        at edu.wpi.first.wpilibj.TimedRobot.startCompetition(TimedRobot.java:131)
        at edu.wpi.first.wpilibj.RobotBase.runRobot(RobotBase.java:350)
        at edu.wpi.first.wpilibj.RobotBase.lambda$startRobot$0(RobotBase.java:418)
        at java.base/java.lang.Thread.run(Thread.java:842)

The behavior is sporadic; making a code change and rebuilding + restarting the simulation will occasionally fix the issue temporarily. ./gradlew clean has also occasionally solved it, at worst I have gone as far as manually purging all build directories (.gradle/, bin/, build/) to resolve runtime errors. Repeatedly rebuilding without any intervention does not mitigate the issue. If ExampleSubsystem is excluded, issues are much more seldom but still occur. Runtime errors are sensibly reflected in bin/generated-sources/, but interestingly artifacts in build/generated/sources/ never have problems. I'm not an expert on how annotation processors and gradle interact in the slightest, however my blind intuition is that there exists a race condition between Epilogue finishing logger generation and gradle compiling.

Desktop

  • OS: Windows 11
  • build.gradle:
plugins {
    id "java"
    id "edu.wpi.first.GradleRIO" version "2025.0.0-alpha-2"
}

wpi.maven.useLocal = false
wpi.maven.useDevelopment = true
wpi.versions.wpilibVersion = '2025.+'
wpi.versions.wpimathVersion = '2025.+'

// ...

dependencies {
    annotationProcessor wpi.java.deps.wpilibAnnotations()
    implementation wpi.java.deps.wpilib()
    implementation wpi.java.vendor.java()
    // ...
}
  • Project Information:
Project Version: 2025.0.0-alpha-2
VS Code Version: 1.85.1
WPILib Extension Version: 2024.3.2
C++ Extension Version: 1.20.0
Java Extension Version: 1.26.2023121408
Java Debug Extension Version: 0.55.2023121302
Java Dependencies Extension Version 0.23.2023120100
Java Version: 17
Java Location: C:\Users\Public\wpilib\2024\jdk
Vendor Libraries:
   WPILib-New-Commands (1.0.0)

(Note that this behavior is also seen when using GradleRIO 2024.3.2)

@BR88C BR88C changed the title [epilogue] Inconsistent generation leading to runtime errors [epilogue] Sporadic runtime errors Sep 20, 2024
@rzblue rzblue added type: bug Something isn't working. component: epilogue Annotation-based logging library labels Sep 20, 2024
@SamCarlberg
Copy link
Member

bin/generated-sources/

This is not a directory generated by Gradle. Generated sources are in build/generated/sources, which you report are correct. I don't know what would be generating this bin directory, nor why it would be included in the build and apparently overriding the correct files

@ThadHouse
Copy link
Member

Thats the folder where the redhat Java extension compiles into. When running the debugger, it uses those files, and not the Jar compiled by gradle. We don't control that behavior.

@rzblue
Copy link
Member

rzblue commented Sep 20, 2024

potential related issue:
redhat-developer/vscode-java#2981

@SamCarlberg
Copy link
Member

We've done some more investigation into this problem, and it's likely an issue somewhere with either the Red Hat language server or the Eclipse jdt project it uses for its implementation. In either case, the Eclipse compiler is used to generate the source files created by Epilogue in order for intellisense to pick up the generated source files (eg Epilogue.java). The Eclipse compiler uses incremental compilation to avoid recompiling the entire project when a single file is updated, but for some reason it's not regenerating the Epilogue file when logged classes are created, updated, or removed. This results in partial file generation that crashes at runtime when a bad Epilogue class is loaded by the debugger extension.

A workaround for this would be to run ./gradlew simulateJava directly through a terminal, instead of using the Simulate Robot Program task in vscode. The vscode debugger extension loads the Eclipse-generated classes, not the gradle-built ones, so running the gradle task directly will load the correct classes. You would need to manually attach the debugger to the gradle task, but may behave oddly due to a mismatch between the JLS and gradle generated sources. Intellisense for the generated classes will also get gradually get more and more out of sync with your project, but unless you're doing really custom things with Epilogue, it should be fine since all you need are the Epilogue class and its bind and update methods

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: epilogue Annotation-based logging library type: bug Something isn't working.
Projects
None yet
4 participants