Skip to content

Commit

Permalink
Support adding -Djdk.attach.allowAttachSelf to jack-in params
Browse files Browse the repository at this point in the history
Add `cider-enable-nrepl-jvmti-agent` customizable to control this behaviour.
  • Loading branch information
alexander-yakushev committed Jun 2, 2024
1 parent 5f79b02 commit c413df6
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 6 deletions.
22 changes: 17 additions & 5 deletions cider.el
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ then concatenated into the \"-M[your-aliases]:cider/nrepl\" form."
:safe #'stringp
:package-version '(cider . "1.1"))


(defcustom cider-clojure-cli-global-aliases
nil
"Global aliases to include when jacking in with the clojure CLI.
Expand All @@ -186,7 +185,6 @@ then concatenated into the \"-M[your-aliases]:cider/nrepl\" form."
:safe #'stringp
:package-version '(cider . "1.14"))


(defcustom cider-shadow-cljs-command
"npx shadow-cljs"
"The command used to execute shadow-cljs.
Expand Down Expand Up @@ -376,6 +374,14 @@ The repl dependendcies are most likely to be nREPL middlewares."
:safe #'booleanp
:version '(cider . "0.11.0"))

(defcustom cider-enable-nrepl-jvmti-agent nil
"When t, add `-Djdk.attach.allowAttachSelf' to the command line arguments.
This allows nREPL JVMTI agent to be loaded. It is needed for evaluation
interruption to properly work on Java 21 and above."
:type 'boolean
:safe #'booleanp
:version '(cider . "1.15.0"))

(defcustom cider-offer-to-open-cljs-app-in-browser t
"When nil, do not offer to open ClojureScript apps in a browser on connect."
:type 'boolean
Expand Down Expand Up @@ -536,7 +542,7 @@ Throws an error if PROJECT-TYPE is unknown."
"List of dependencies where elements are lists of artifact name and version.")
(put 'cider-jack-in-dependencies 'risky-local-variable t)

(defcustom cider-injected-nrepl-version "1.1.2"
(defcustom cider-injected-nrepl-version "1.2.0-beta2"
"The version of nREPL injected on jack-in.
We inject the newest known version of nREPL just in case
your version of Boot or Leiningen is bundling an older one."
Expand Down Expand Up @@ -762,6 +768,9 @@ group:artifact:version notation and MIDDLEWARES are
prepared as arguments to Clojurephant's ClojureNRepl task."
(concat global-opts
(unless (seq-empty-p global-opts) " ")
(if cider-enable-nrepl-jvmti-agent
(shell-quote-argument "-Pjdk.attach.allowAttachSelf"))
(when cider-enable-nrepl-jvmti-agent " ")
(cider--gradle-jack-in-property (append (cider--jack-in-required-dependencies) dependencies))
" "
params
Expand Down Expand Up @@ -813,7 +822,9 @@ removed, LEIN-PLUGINS, LEIN-MIDDLEWARES and finally PARAMS."
(seq-map (lambda (middleware)
(concat "update-in :middleware conj "
middleware))
lein-middlewares))
lein-middlewares)
(when cider-enable-nrepl-jvmti-agent
`(,(concat "update-in :jvm-opts conj " (shell-quote-argument "-Djdk.attach.allowAttachSelf")))))
" -- ")
" -- "
(if (not cider-enrich-classpath)
Expand Down Expand Up @@ -903,9 +914,10 @@ your aliases contain any mains, the cider/nrepl one will be the one used."
(deps (format "{:deps {%s} :aliases {:cider/nrepl {:main-opts [%s]}}}"
(string-join all-deps " ") main-opts))
(deps-quoted (cider--shell-quote-argument deps command)))
(format "%s-Sdeps %s -M%s:cider/nrepl%s"
(format "%s%s-Sdeps %s -M%s:cider/nrepl%s"
;; TODO: global-options are deprecated and should be removed in CIDER 2.0
(if global-options (format "%s " global-options) "")
(if cider-enable-nrepl-jvmti-agent "-J-Djdk.attach.allowAttachSelf " "")
deps-quoted
(cider--combined-aliases)
(if params (format " %s" params) ""))))
Expand Down
8 changes: 8 additions & 0 deletions doc/modules/ROOT/pages/basics/up_and_running.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,14 @@ You can further customize the command line CIDER uses for `cider-jack-in` by
modifying the some options. Those differ a bit between the various tools,
so we'll examine them tool by tool.

==== Enabling nREPL JVMTI agent

Since version 1.2.0, nREPL ships together with a native JVMTI agent, so that the
eval interrupts properly work on Java 20 and later. To enable the agent, the
Java process should be launched with `-Djdk.attach.allowAttachSelf`. CIDER will
do it automatically during jack-in if you change
`cider-enable-nrepl-jvmti-agent` customizable to `t`.

==== Leiningen Options

* `cider-lein-command` - the name of the Leiningen executable (`lein` by default)
Expand Down
6 changes: 6 additions & 0 deletions doc/modules/ROOT/pages/usage/code_evaluation.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ NOTE: CIDER internally increases the timeout to 30 seconds for the first sync ev

== Configuration

=== Enable evaluation interrupts on Java 21 and newer

Special variable `cider-enable-nrepl-jvmti-agent` has to be enabled for
interrupts to work properly on Java 21+. See
xref:basics/up_and_running.adoc#enabling-nrepl-jvmti-agent[JVMTI agent] section.

=== Display Spinner During Evaluation

Some evaluation operations take a while to complete, so CIDER will display a
Expand Down
14 changes: 13 additions & 1 deletion test/cider-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@
(setq-local cider-injected-middleware-version "0.49.0")
(setq-local cider-jack-in-nrepl-middlewares '("cider.nrepl/cider-middleware"))
(setq-local cider-jack-in-dependencies-exclusions '())
(setq-local cider-enrich-classpath t))
(setq-local cider-enrich-classpath t)
(setq-local cider-enable-nrepl-jvmti-agent t))

(it "can inject dependencies in a lein project"
(expect (cider-inject-jack-in-dependencies "" "repl :headless" 'lein)
Expand All @@ -157,6 +158,7 @@
(shell-quote-argument "[cider/cider-nrepl \"0.49.0\"]")
" -- update-in :plugins conj "
(shell-quote-argument "[mx.cider/lein-enrich-classpath \"1.19.3\"]")
" -- update-in :jvm-opts conj -Djdk.attach.allowAttachSelf"
" -- update-in :middleware conj cider.enrich-classpath.plugin-v2/middleware"
" -- repl :headless")))

Expand All @@ -170,6 +172,7 @@
(shell-quote-argument "[cider/cider-nrepl \"0.49.0\"]")
" -- update-in :plugins conj "
(shell-quote-argument "[mx.cider/lein-enrich-classpath \"1.19.3\"]")
" -- update-in :jvm-opts conj -Djdk.attach.allowAttachSelf"
" -- update-in :middleware conj cider.enrich-classpath.plugin-v2/middleware"
" -- repl :headless")))

Expand All @@ -182,6 +185,7 @@
(shell-quote-argument "[cider/cider-nrepl \"0.49.0\"]")
" -- update-in :plugins conj "
(shell-quote-argument "[mx.cider/lein-enrich-classpath \"1.19.3\"]")
" -- update-in :jvm-opts conj -Djdk.attach.allowAttachSelf"
" -- update-in :middleware conj cider.enrich-classpath.plugin-v2/middleware"
" -- repl :headless")))

Expand All @@ -201,6 +205,7 @@
(it "can inject dependencies in a gradle project"
(expect (cider-inject-jack-in-dependencies "--no-daemon" ":clojureRepl" 'gradle)
:to-equal (concat "--no-daemon "
"-Pjdk.attach.allowAttachSelf "
(shell-quote-argument "-Pdev.clojurephant.jack-in.nrepl=nrepl:nrepl:0.9.0,cider:cider-nrepl:0.49.0")
" :clojureRepl "
(shell-quote-argument "--middleware=cider.nrepl/cider-middleware")))))
Expand All @@ -221,6 +226,7 @@
(shell-quote-argument "[cider/cider-nrepl \"0.49.0\"]")
" -- update-in :plugins conj "
(shell-quote-argument "[mx.cider/lein-enrich-classpath \"1.19.3\"]")
" -- update-in :jvm-opts conj -Djdk.attach.allowAttachSelf"
" -- update-in :middleware conj cider.enrich-classpath.plugin-v2/middleware"
" -- repl :headless")))

Expand Down Expand Up @@ -256,6 +262,7 @@
(shell-quote-argument "[cider/cider-nrepl \"0.49.0\"]")
" -- update-in :plugins conj "
(shell-quote-argument "[mx.cider/lein-enrich-classpath \"1.19.3\"]")
" -- update-in :jvm-opts conj -Djdk.attach.allowAttachSelf"
" -- update-in :middleware conj cider.enrich-classpath.plugin-v2/middleware"
" -- repl :headless")))
(it "can concat in a boot project"
Expand All @@ -272,6 +279,7 @@
(it "can concat in a gradle project"
(expect (cider-inject-jack-in-dependencies "--no-daemon" ":clojureRepl" 'gradle)
:to-equal (concat "--no-daemon "
"-Pjdk.attach.allowAttachSelf "
(shell-quote-argument "-Pdev.clojurephant.jack-in.nrepl=nrepl:nrepl:0.9.0,cider:cider-nrepl:0.49.0")
" :clojureRepl "
(shell-quote-argument "--middleware=cider.nrepl/cider-middleware")))))
Expand Down Expand Up @@ -337,6 +345,7 @@
(shell-quote-argument "[cider/cider-nrepl \"0.49.0\"]")
" -- update-in :plugins conj "
(shell-quote-argument "[mx.cider/lein-enrich-classpath \"1.19.3\"]")
" -- update-in :jvm-opts conj -Djdk.attach.allowAttachSelf"
" -- update-in :middleware conj cider.enrich-classpath.plugin-v2/middleware"
" -- repl :headless"))))

Expand Down Expand Up @@ -454,6 +463,7 @@
(setq-local cider-clojure-cli-command "clojure")
(setq-local cider-inject-dependencies-at-jack-in t)
(setq-local cider-clojure-cli-aliases nil)
(setq-local cider-enable-nrepl-jvmti-agent t)
(spy-on 'cider-project-type :and-return-value 'clojure-cli)
(spy-on 'cider-jack-in-resolve-command :and-return-value "clojure")
(expect (plist-get (cider--update-jack-in-cmd nil) :jack-in-cmd)
Expand All @@ -469,6 +479,7 @@
(setq-local cider-allow-jack-in-without-project t)
(setq-local cider-clojure-cli-command "clojure")
(setq-local cider-inject-dependencies-at-jack-in t)
(setq-local cider-enable-nrepl-jvmti-agent t)
(spy-on 'cider-project-type :and-return-value 'clojure-cli)
(spy-on 'cider-jack-in-resolve-command :and-return-value "clojure")
(expect (plist-get (cider--update-jack-in-cmd nil) :jack-in-cmd)
Expand Down Expand Up @@ -534,6 +545,7 @@
(setq-local cider-clojure-cli-command "clojure")
(setq-local cider-inject-dependencies-at-jack-in t)
(setq-local cider-clojure-cli-aliases nil)
(setq-local cider-enable-nrepl-jvmti-agent t)
(spy-on 'cider-project-type :and-return-value 'clojure-cli)
(spy-on 'cider-jack-in-resolve-command :and-return-value "clojure")
(expect (plist-get (cider--update-jack-in-cmd nil) :jack-in-cmd)
Expand Down

0 comments on commit c413df6

Please sign in to comment.