Fork me on GitHub
#graalvm
<
2020-07-20
>
borkdude12:07:24

I'm getting the locking issue while compiling a library (datalevin) with GraalVM native-image. Haven't dug deeply into this yet. Could be that some AOT-ed thing is left on the classpath that brings in the old locking stuff, but the source which occurs in the error output is not AOT-ed I believe: https://github.com/borkdude/datalevin-native

borkdude13:07:25

Hmm, I believe this repros it:

(defprotocol IFoo
  (store [_]))

(deftype Foo [^:volatile-mutable ^long max-gt]
  IFoo
  (store [_]
    (locking max-gt
      (println "Stored!"))))

(defn -main [& _args]
  (let [foo (Foo. 10)]
    (store foo))

borkdude13:07:53

Error: unbalanced monitors: mismatch at monitorexit, 7|Invoke#Numbers.num != 52|Invoke#Numbers.num
Detailed message:
Call path from entry point to borkdude.datalevin_native.main.Foo.store():
	at borkdude.datalevin_native.main.Foo.store(main.clj:14)

borkdude13:07:47

I'll make a dedicated repro repo in a few hours, and I'll add some comment to CLJ-1472 (cc @alexmiller)

borkdude13:07:54

Aha! When I remove the ^long type hint, then it compiles:

(defprotocol IFoo
  (store [_]))

(deftype Foo [^long max-gt]
  IFoo
  (store [_]
    (locking max-gt
      (println "Stored!"))))

(defn -main [& _args]
  (let [foo (Foo. 10)]
    (store foo)))

alexmiller13:07:16

just file a new ticket

alexmiller13:07:24

and link to CLJ-1472

alexmiller13:07:10

wait, you can't lock on a primitive long - it has to be an object

alexmiller13:07:17

that code doesn't make sense

alexmiller13:07:09

yeah, that's bad

borkdude13:07:07

so it does not work, but it doesn't fail in the JVM either?

alexmiller13:07:40

my guess would be that in some cases the primitive long is getting up cast. that's the only way it could work (but locking on a Long value is still a bad idea). this code is just wrong.

alexmiller13:07:09

the Java numeric value objects can be cached around 0 and that means the scope of your Long sharing can escape your own code (similarly, you should never lock on a String instance which might be interned)

borkdude13:07:17

:thumbsup: I'll make an issue with this conversation in their repo

alexmiller13:07:24

it's best to make an explicit lock Object