Fork me on GitHub

Hi! On NixOS I get

1: (babashka.process/exec ["echo" "foo"])
   ^--- exec is not supported in non-GraalVM environments
when running bb -e '(babashka.process/exec ["echo" "foo"])'. Any ideas why? As far as I understand it, the check and error message is only supposed to show up when using babaska.process as a JVM dependency from Clojure.


I'm not sure how the nixos binary is compiled. Can you try the binary that babashka distributes via github releases?


the linux static binary should work in nix as well


Yep, the static binary works.


But it's probably out of scope for you to debug. I'll try to find out what's going on.


does it use the regular graalvm ce version?


probably @UKFSJSM38 or @UFDRD93RR would know more


the check that is done to enable exec is here: it checks at compile time if the graalvm class is available


so if the uberjar is built using openjdk / non-graalvm it will still fail probably. it's recommended to build both the uberjar and native-image using the same graalvm


Ah, that probably explains it. It uses the babashka-standalone jar from the github releases.


hmm, the uberjar is made using graalvm though


at least, I would expect that


well maybe not and that could be the issue


that is probably the issue...

openjdk version "11.0.15" 2022-04-19
OpenJDK Runtime Environment 18.9 (build 11.0.15+10)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.15+10, mixed mode, sharing)


I'll fix that


can you test with an uberjar from CI later?


@U0303ET1R2T Yes, this was it. old:

$ $GRAALVM_HOME/bin/java -classpath "$(clojure -Spath):babashka-1.0.165-standalone.jar"  clojure.main -e "(require '[babashka.process]) (babashka.process/exec [\"ls\"])"
Execution error (ExceptionInfo) at babashka.process/exec (process.cljc:542).
exec is not supported in non-GraalVM environments
$ $GRAALVM_HOME/bin/java -classpath "$(clojure -Spath):babashka-1.0.166-SNAPSHOT-standalone.jar"  clojure.main -e "(require '[babashka.process]) (babashka.process/exec [\"ls\"])"
Execution error (Error) at org.graalvm.nativeimage.impl.ImageSingletonsSupport/checkInstalled (
The class ImageSingletons can only be used when building native images, i.e., when using the native-image command.
The new error is what I would expect since I'm not running with native image here, but if you compile it to native with this uberjar, exec should work


Can you test this locally?


Yep, works! Thanks a lot!


I've found this useful (it has clojure.core/swap! semantics but applies to files):

(defn swap-file!
  "Swaps the contents of file to be:
  (apply f current-contents-of-file args). f should be free of side effects.
  Returns the value that was swapped in."
  [file f & xs]
  (let [old-val (slurp file)
        new-val (apply f old-val xs)]
    (spit file new-val)
if there's any interest I could raise a PR for babashka/fs...

😍 6
pavlosmelissinos21:11:44 I'm not so sure about the name (or the trailing ! since no other function in babashka.fs uses it), swap-file! kind of resembles swap! but replace-file might be more intuitive and update-file more familiar? :thinking_face: Happy to change any part of it, just let me know on Github/here (it's a bit late here though so I might not see it until tomorrow)...


hm yeah, I like update-something

🆗 1

Will take a look tomorrow, thanks!

🙂 1

maybe it shouldn't be called swap-file! as it's not free of race conditions (another thread/process can write between the slurp and the spit). It could be made thread safe though with some file locking (but I'm unsure how portable such file locking can be made. Im only familiar with fcntl style locking on posix)


it's now called update-file in the PR

👍 1

> another thread/process can write between the slurp and the spit That's true @U1QQJJK89! However, a file is a shared resource that is not really owned by the JVM so I'm not sure how easy it is to prevent external processes from accessing it (especially across platforms) 😞 I think it can be made thread-safe (within the JVM process) with clojure.core/locking on the file but then the test becomes a bit weird (I have to add a Thread/sleep and a couple of futures) and it causes other problems, e.g. potential deadlock


In clj-kondo I have some inter-process locking stuff, but I think that's going too far for this function. The 99.9% scripting case is covered here

👍 1

we can just add to the docstring that it isn't thread-safe, but I think the docstring already reflects that


Also f doesn't need to be free of side effects here, as it is only ever run once. Could remove that part of the docstring.


Hmm, f should just be a function that processes a string. That's not to say you can't have side effects in it at all, it's just weird. The PR was merged (thanks @U04V15CAJ!) but go ahead and suggest a fix if you think the docstring is misleading 🙂.


It's ok, was just noting. In swap! functions need to be free of side effects because they can be rerun multiple times. This being only run once you are free to add a side effect without problems. Maybe you want to increment a counter on how many times the file has been updated. You could do this in your function here if you wanted to without ill effect.

👍 1

Its not a big deal. If borkdudes happy with it that's ok with me.


Yes, I wanted to change that too, it can have side effects :)


PR welcome in case I forget


I've been using this pattern over and over myself too .. I like it :)

🙂 1