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

Scala Native crash when wrong cached ClassLoader is used #4177

Open
lolgab opened this issue Dec 24, 2024 · 0 comments
Open

Scala Native crash when wrong cached ClassLoader is used #4177

lolgab opened this issue Dec 24, 2024 · 0 comments
Labels
bug The issue represents an bug workaround-available

Comments

@lolgab
Copy link
Member

lolgab commented Dec 24, 2024

Given a Cross ScalaNativeModule, multiple classloaders are used,
Since we cache the output nativeConfig, it can happen that a nativeConfig generated
with a Classloader is used when linking with another classloader.
This can lead to ClassCastException since objects from different classloader can't be shared.

Repro

import mill._
import mill.scalalib._
import mill.scalanativelib._

object app extends Cross[App]("a", "b", "c", "d")
trait App extends ScalaNativeModule with Cross.Module[String] {
  def scalaVersion = "3.5.2"
  def scalaNativeVersion = "0.5.6"
}
mill __.nativeLink

Output

app[aarch64-macos-none].nativeLink java.lang.ClassCastException: class scala.scalanative.build.Config$Impl cannot be cast to class scala.scalanative.build.Config (scala.scalanative.build.Config$Impl is in unnamed module of loader mill.api.ClassLoader$$anon$1 @278c6ad9; scala.scalanative.build.Config is in unnamed module of loader mill.api.ClassLoader$$anon$1 @3d4e7cb1)
    mill.scalanativelib.worker.ScalaNativeWorkerImpl.nativeLink(ScalaNativeWorkerImpl.scala:105)
    mill.scalanativelib.ScalaNativeModule.$anonfun$nativeLink$4(ScalaNativeModule.scala:286)
    mill.scalanativelib.ScalaNativeModule$ScalaNativeBridge.$anonfun$apply$1(ScalaNativeModule.scala:159)
    mill.api.CachedFactory.withValue(CachedFactory.scala:39)
    mill.scalanativelib.ScalaNativeModule$ScalaNativeBridge.apply(ScalaNativeModule.scala:158)
    mill.scalanativelib.ScalaNativeModule.$anonfun$nativeLink$3(ScalaNativeModule.scala:287)
app[aarch64-windows-gnu].nativeLink scala.scalanative.build.BuildException: Failed to compile /Users/lorenzo/scala/scala-native-cross/out/app/aarch64-windows-gnu/nativeWorkdir.dest/native/dependencies/nativelib_native0.5_3-0.5.6-0/scala-native/nativeThreadTLS.c
app[x86_64-linux-gnu].nativeLink java.lang.ClassCastException: class scala.scalanative.build.Config$Impl cannot be cast to class scala.scalanative.build.Config (scala.scalanative.build.Config$Impl is in unnamed module of loader mill.api.ClassLoader$$anon$1 @2bd047bc; scala.scalanative.build.Config is in unnamed module of loader mill.api.ClassLoader$$anon$1 @709c8fd6)
    mill.scalanativelib.worker.ScalaNativeWorkerImpl.nativeLink(ScalaNativeWorkerImpl.scala:105)
    mill.scalanativelib.ScalaNativeModule.$anonfun$nativeLink$4(ScalaNativeModule.scala:286)
    mill.scalanativelib.ScalaNativeModule$ScalaNativeBridge.$anonfun$apply$1(ScalaNativeModule.scala:159)
    mill.api.CachedFactory.withValue(CachedFactory.scala:39)
    mill.scalanativelib.ScalaNativeModule$ScalaNativeBridge.apply(ScalaNativeModule.scala:158)
    mill.scalanativelib.ScalaNativeModule.$anonfun$nativeLink$3(ScalaNativeModule.scala:287)

Possible solutions

  • Add the module as the cache key, to make a module always use the same ClassLoader.

Workaround

Pass -j 1 so a single Classloader is used.

@lolgab lolgab added bug The issue represents an bug workaround-available labels Dec 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug The issue represents an bug workaround-available
Projects
None yet
Development

No branches or pull requests

1 participant