librelist archives

« back to archive

Leiningen, Windows and process management

Leiningen, Windows and process management

From:
Laurent Petit
Date:
2014-01-19 @ 21:12
Hello,

Counterclockwise has now a mode where it delegates entirely to Leiningen
the launch of a headless REPL.

Counterclockwise manages the Leiningen Process, which in turn creates the
project's process (*).

On Linux/OS X, when the user "kills" the Leiningen Process via
Counterclockwise, the project's process is also killed (probably due to a
parent / child relationship between processes?).

But this doesn't work on Windows : the project's process remains on the
background, generally unnoticed until the accumulation of those processes
eats up too much memory, etc.

What are my options for addressing this specific common usage (or better,
the general case) ?

- I have thought that maybe I could always force the "trampoline" mode. But
are there some kinds of tasks that require both process to stay alive (for
instance, for polling the project files for changes and on-the-fly
recompilation, whatever) ? Or are those things always piloted via the
project process? => Is it safe to always use the Trampoline mode ?
- Another option ?

Thanks in advance for your suggestions,

-- 
Laurent


(*) it does not directly use the bash / bat scripts. Rather, it creates the
command line to call java with leiningen-standalone on the classpath, and
invokes leiningen.main with the user command.

Re: [leiningen] Leiningen, Windows and process management

From:
Jean Niklas L'orange
Date:
2014-01-20 @ 00:35
Hello Laurent,

I actually had to look around to fix a similar problem in Leiningen, where
the shutdown hooks in subprocesses were not activated, and I think I can
point you in the right direction.

The project process is handled by the `sh` command, which adds a shutdown
hook to its child process, killing it if the main Leiningen JVM is
interrupted or gracefully exits. See:

https://github.com/technomancy/leiningen/blob/919bf67d8d06adcda72012c531ca99f724950eb7/leiningen-core/src/leiningen/core/eval.clj#L160-L161

When the main JVM is forcibly terminated however, the shutdown hooks aren't
able to run, and the children may or may not be killed, depending on the
OS's child/parent relationship. The only way to ensure that they are
killed, is by ensuring that the Lein process is gracefully terminated.

I guess the problem is that you perform a

.destroy()<http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html#destroy()>method
on the subprocess, meaning that it is "is
forcibly terminated". As such, the Lein JVM cannot run its shutdown hooks.

I can't point towards a specific solution, but if this is indeed the
problem, you need to find a way to gracefully shut the Lein JVM down.


On 19 January 2014 22:12, Laurent PETIT <laurent.petit@gmail.com> wrote:

> Hello,
>
> Counterclockwise has now a mode where it delegates entirely to Leiningen
> the launch of a headless REPL.
>
> Counterclockwise manages the Leiningen Process, which in turn creates the
> project's process (*).
>
> On Linux/OS X, when the user "kills" the Leiningen Process via
> Counterclockwise, the project's process is also killed (probably due to a
> parent / child relationship between processes?).
>
> But this doesn't work on Windows : the project's process remains on the
> background, generally unnoticed until the accumulation of those processes
> eats up too much memory, etc.
>
> What are my options for addressing this specific common usage (or better,
> the general case) ?
>
> - I have thought that maybe I could always force the "trampoline" mode.
> But are there some kinds of tasks that require both process to stay alive
> (for instance, for polling the project files for changes and on-the-fly
> recompilation, whatever) ? Or are those things always piloted via the
> project process? => Is it safe to always use the Trampoline mode ?
> - Another option ?
>
> Thanks in advance for your suggestions,
>
> --
> Laurent
>
>
> (*) it does not directly use the bash / bat scripts. Rather, it creates
> the command line to call java with leiningen-standalone on the classpath,
> and invokes leiningen.main with the user command.
>



-- 
Regards,
Jean Niklas L'orange

Re: [leiningen] Leiningen, Windows and process management

From:
Phil Hagelberg
Date:
2014-01-20 @ 22:08
Laurent PETIT writes:

> ... also, using trampoline with lein repl :headless opens the opportunity
> to cache the "command line" for future usages, until invalidated by e.g.
> changes to project/profile.clj, etc.

This is already implemented in Leiningen; see the `LEIN_FAST_TRAMPOLINE`
setting. While trampolining would work fine for single task invocations,
once you get into task chains it starts to become problematic because it
collapses all eval-in-project calls into a single one that is deferred
until after all the other tasks have run. If some of the middle tasks
depend on a compilation that's supposed to happen up-front, you'll get
unpredictable behaviour.

> I'm also worried about that. It has bitten me in the past: CCW uses "lein
> new" and allows the user to specify arbitrary lein-newnew templates. And it
> happens that when the user was wrong in typing a template name, what
> lein-newnew does is call leiningen.core/abort which does a (System/exit 0) !

There's actually nothing wrong with this; you can just rebind
`leiningen.core.main/*exit-process?*` in order to indicate that you
don't want errors to exit the whole JVM. There still may be plugins out
there that call System/exit directly; and there's nothing we can do
about that except report them as bugs. But I believe those are fairly rare.

> This is clearly again the manifestation that at its core lein is still
> oriented towards quickly executing a task then exiting.
> Or at least, that plugin writers program towards its API with this mindset.

I can't speak for third-party plugins, but I've tried pretty hard to
ensure that whatever process is running Leiningen itself is re-usable
for multiple task executions. In fact, Grenchman takes advantage of that
as you can see here:

    https://github.com/technomancy/grenchman/blob/master/lein.ml

I suspect the only issue you'll see with third-party plugins is that
they assume the directory from which the JVM was launched is always the
project root rather than checking the `:root` entry of the project map
or the binding of `leiningen.core.main/*cwd*`. But this is easy to fix
in any given plugin once you've identified the problem.

The main remaining reason I could see for using a separate process would
just be in order to avoid version conflicts between CCW dependencies and
the dependencies of Leiningen and its plugins. Working within the
constraints of compatibility with Leiningen's dependencies probably
wouldn't be too difficult, but since plugins can bring in pretty much
anything, it's tricky to foresee how big of a problem this could be in
the future.

-Phil

Re: [leiningen] Leiningen, Windows and process management

From:
Colin Fleming
Date:
2014-01-21 @ 00:08
<snip>

> There's actually nothing wrong with this; you can just rebind
> `leiningen.core.main/*exit-process?*` in order to indicate that you
> don't want errors to exit the whole JVM. There still may be plugins out
> there that call System/exit directly; and there's nothing we can do
> about that except report them as bugs. But I believe those are fairly rare.
>

Ah, you're right, abort calls exit, not the other way around. I'm actually
already rebinding *exit-process?* and it's working well in Cursive, so this
should work for you as well, Laurent.


> > This is clearly again the manifestation that at its core lein is still
> > oriented towards quickly executing a task then exiting.
> > Or at least, that plugin writers program towards its API with this
> mindset.
>
> I can't speak for third-party plugins, but I've tried pretty hard to
> ensure that whatever process is running Leiningen itself is re-usable
> for multiple task executions. In fact, Grenchman takes advantage of that
> as you can see here:
>
>     https://github.com/technomancy/grenchman/blob/master/lein.ml
>
> I suspect the only issue you'll see with third-party plugins is that
> they assume the directory from which the JVM was launched is always the
> project root rather than checking the `:root` entry of the project map
> or the binding of `leiningen.core.main/*cwd*`. But this is easy to fix
> in any given plugin once you've identified the problem.
>
> The main remaining reason I could see for using a separate process would
> just be in order to avoid version conflicts between CCW dependencies and
> the dependencies of Leiningen and its plugins. Working within the
> constraints of compatibility with Leiningen's dependencies probably
> wouldn't be too difficult, but since plugins can bring in pretty much
> anything, it's tricky to foresee how big of a problem this could be in
> the future.
>
> -Phil
>

Re: [leiningen] Leiningen, Windows and process management

From:
Laurent Petit
Date:
2014-02-06 @ 18:18
2014-01-21 Colin Fleming <colin.mailinglist@gmail.com>:

>
> <snip>
>
>> There's actually nothing wrong with this; you can just rebind
>> `leiningen.core.main/*exit-process?*` in order to indicate that you
>> don't want errors to exit the whole JVM. There still may be plugins out
>> there that call System/exit directly; and there's nothing we can do
>> about that except report them as bugs. But I believe those are fairly
>> rare.
>>
>
> Ah, you're right, abort calls exit, not the other way around. I'm actually
> already rebinding *exit-process?* and it's working well in Cursive, so this
> should work for you as well, Laurent.
>

That's a good advice, thanks, I have done that => if
leiningen.core.main/exit is called directly, the JVM won't stop, that's
good :-)

But I have done more, because when abort is called, it is pushing a message
to stdout, and then calling exit.
The result is that when using leiningen-core as an API, and some plugin
calls abort, the abortion message is lost or disseminated with potentially
other stuff in *err*, and I just get an exit-code in the ex-info.

So I have replaced abort with my own, which directly throws an ex-info
keeping the message.

Maybe Leiningen exit could be modified to take optional message arguments,
and abort could pass its message arguments to exit, which, in the "throw"
case, could add an :error-message key to the ex-info ?



>
>
>> > This is clearly again the manifestation that at its core lein is still
>> > oriented towards quickly executing a task then exiting.
>> > Or at least, that plugin writers program towards its API with this
>> mindset.
>>
>> I can't speak for third-party plugins, but I've tried pretty hard to
>> ensure that whatever process is running Leiningen itself is re-usable
>> for multiple task executions. In fact, Grenchman takes advantage of that
>> as you can see here:
>>
>>     https://github.com/technomancy/grenchman/blob/master/lein.ml
>>
>> I suspect the only issue you'll see with third-party plugins is that
>> they assume the directory from which the JVM was launched is always the
>> project root rather than checking the `:root` entry of the project map
>> or the binding of `leiningen.core.main/*cwd*`. But this is easy to fix
>> in any given plugin once you've identified the problem.
>>
>> The main remaining reason I could see for using a separate process would
>> just be in order to avoid version conflicts between CCW dependencies and
>> the dependencies of Leiningen and its plugins. Working within the
>> constraints of compatibility with Leiningen's dependencies probably
>> wouldn't be too difficult, but since plugins can bring in pretty much
>> anything, it's tricky to foresee how big of a problem this could be in
>> the future.
>>
>> -Phil
>>
>
>

Re: [leiningen] Leiningen, Windows and process management

From:
Laurent Petit
Date:
2014-01-20 @ 10:22
Hello Jean,


2014/1/20 Jean Niklas L'orange <jeannikl@hypirion.com>

> Hello Laurent,
>
> I actually had to look around to fix a similar problem in Leiningen, where
> the shutdown hooks in subprocesses were not activated, and I think I can
> point you in the right direction.
>
> The project process is handled by the `sh` command, which adds a shutdown
> hook to its child process, killing it if the main Leiningen JVM is
> interrupted or gracefully exits. See:
>
> 
https://github.com/technomancy/leiningen/blob/919bf67d8d06adcda72012c531ca99f724950eb7/leiningen-core/src/leiningen/core/eval.clj#L160-L161
>
> When the main JVM is forcibly terminated however, the shutdown hooks
> aren't able to run, and the children may or may not be killed, depending on
> the OS's child/parent relationship. The only way to ensure that they are
> killed, is by ensuring that the Lein process is gracefully terminated.
>
> I guess the problem is that you perform a 
.destroy()<http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html#destroy()>method
on the subprocess, meaning that it is "is
> forcibly terminated". As such, the Lein JVM cannot run its shutdown hooks.
>
> I can't point towards a specific solution, but if this is indeed the
> problem, you need to find a way to gracefully shut the Lein JVM down.
>
>
It's nice that the hook is already in place in Leiningen.
Alas, I've done some tests, and the default Eclipse behaviour is to
.destroy() the subprocess, thus the shutdown hooks indeed aren't triggered.

So I'm left with considering the Trampoline all over the place option.
But I'm far from a trampoline expert :

- can trampolining be forced by the user (and thus by Eclipse/CCW) in any
case, or should the task to be launched be "trampoline compatible" ?

- if not applicable in the general case, can trampoline be used with "lein
repl :headless" ?



>
> On 19 January 2014 22:12, Laurent PETIT <laurent.petit@gmail.com> wrote:
>
>> Hello,
>>
>> Counterclockwise has now a mode where it delegates entirely to Leiningen
>> the launch of a headless REPL.
>>
>> Counterclockwise manages the Leiningen Process, which in turn creates the
>> project's process (*).
>>
>> On Linux/OS X, when the user "kills" the Leiningen Process via
>> Counterclockwise, the project's process is also killed (probably due to a
>> parent / child relationship between processes?).
>>
>> But this doesn't work on Windows : the project's process remains on the
>> background, generally unnoticed until the accumulation of those processes
>> eats up too much memory, etc.
>>
>> What are my options for addressing this specific common usage (or better,
>> the general case) ?
>>
>> - I have thought that maybe I could always force the "trampoline" mode.
>> But are there some kinds of tasks that require both process to stay alive
>> (for instance, for polling the project files for changes and on-the-fly
>> recompilation, whatever) ? Or are those things always piloted via the
>> project process? => Is it safe to always use the Trampoline mode ?
>> - Another option ?
>>
>> Thanks in advance for your suggestions,
>>
>> --
>> Laurent
>>
>>
>> (*) it does not directly use the bash / bat scripts. Rather, it creates
>> the command line to call java with leiningen-standalone on the classpath,
>> and invokes leiningen.main with the user command.
>>
>
>
>
> --
> Regards,
> Jean Niklas L'orange
>

Re: [leiningen] Leiningen, Windows and process management

From:
Colin Fleming
Date:
2014-01-20 @ 10:46
Trampoline can definitely be used with "lein repl :headless", that's what
Cursive is currently doing to start its Leiningen-based REPLs. I call the
trampoline code in-process, then use the trampoline parameters to create
the REPL process directly rather than creating the trampoline script. I
call (leiningen.repl/repl project ":headless"), setting the
leiningen.trampoline/*trampoline?* flag to true, and then use
leiningen.core.eval/trampoline-project/-forms/-profiles to build my command
line.


On 20 January 2014 23:22, Laurent PETIT <laurent.petit@gmail.com> wrote:

> Hello Jean,
>
>
> 2014/1/20 Jean Niklas L'orange <jeannikl@hypirion.com>
>
>> Hello Laurent,
>>
>> I actually had to look around to fix a similar problem in Leiningen,
>> where the shutdown hooks in subprocesses were not activated, and I think I
>> can point you in the right direction.
>>
>> The project process is handled by the `sh` command, which adds a shutdown
>> hook to its child process, killing it if the main Leiningen JVM is
>> interrupted or gracefully exits. See:
>>
>> 
https://github.com/technomancy/leiningen/blob/919bf67d8d06adcda72012c531ca99f724950eb7/leiningen-core/src/leiningen/core/eval.clj#L160-L161
>>
>> When the main JVM is forcibly terminated however, the shutdown hooks
>> aren't able to run, and the children may or may not be killed, depending on
>> the OS's child/parent relationship. The only way to ensure that they are
>> killed, is by ensuring that the Lein process is gracefully terminated.
>>
>> I guess the problem is that you perform a 
.destroy()<http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html#destroy()>method
on the subprocess, meaning that it is "is
>> forcibly terminated". As such, the Lein JVM cannot run its shutdown hooks.
>>
>> I can't point towards a specific solution, but if this is indeed the
>> problem, you need to find a way to gracefully shut the Lein JVM down.
>>
>>
> It's nice that the hook is already in place in Leiningen.
> Alas, I've done some tests, and the default Eclipse behaviour is to
> .destroy() the subprocess, thus the shutdown hooks indeed aren't triggered.
>
> So I'm left with considering the Trampoline all over the place option.
> But I'm far from a trampoline expert :
>
> - can trampolining be forced by the user (and thus by Eclipse/CCW) in any
> case, or should the task to be launched be "trampoline compatible" ?
>
> - if not applicable in the general case, can trampoline be used with "lein
> repl :headless" ?
>
>
>
>>
>> On 19 January 2014 22:12, Laurent PETIT <laurent.petit@gmail.com> wrote:
>>
>>> Hello,
>>>
>>> Counterclockwise has now a mode where it delegates entirely to Leiningen
>>> the launch of a headless REPL.
>>>
>>> Counterclockwise manages the Leiningen Process, which in turn creates
>>> the project's process (*).
>>>
>>> On Linux/OS X, when the user "kills" the Leiningen Process via
>>> Counterclockwise, the project's process is also killed (probably due to a
>>> parent / child relationship between processes?).
>>>
>>> But this doesn't work on Windows : the project's process remains on the
>>> background, generally unnoticed until the accumulation of those processes
>>> eats up too much memory, etc.
>>>
>>> What are my options for addressing this specific common usage (or
>>> better, the general case) ?
>>>
>>> - I have thought that maybe I could always force the "trampoline" mode.
>>> But are there some kinds of tasks that require both process to stay alive
>>> (for instance, for polling the project files for changes and on-the-fly
>>> recompilation, whatever) ? Or are those things always piloted via the
>>> project process? => Is it safe to always use the Trampoline mode ?
>>> - Another option ?
>>>
>>> Thanks in advance for your suggestions,
>>>
>>> --
>>> Laurent
>>>
>>>
>>> (*) it does not directly use the bash / bat scripts. Rather, it creates
>>> the command line to call java with leiningen-standalone on the classpath,
>>> and invokes leiningen.main with the user command.
>>>
>>
>>
>>
>> --
>> Regards,
>> Jean Niklas L'orange
>>
>
>

Re: [leiningen] Leiningen, Windows and process management

From:
Laurent Petit
Date:
2014-01-20 @ 10:54
Hi Colin,


2014/1/20 Colin Fleming <colin.mailinglist@gmail.com>

> Trampoline can definitely be used with "lein repl :headless", that's what
> Cursive is currently doing to start its Leiningen-based REPLs. I call the
> trampoline code in-process, then use the trampoline parameters to create
> the REPL process directly rather than creating the trampoline script. I
> call (leiningen.repl/repl project ":headless"), setting the
> leiningen.trampoline/*trampoline?* flag to true, and then use
> leiningen.core.eval/trampoline-project/-forms/-profiles to build my command
> line.
>

Thanks for sharing the information!

Does that mean that you did some analysis of what is done when "lein rel
:headless" is generally invoked in a "black-box" manner from the
command-line, and that you re-do the same think "in-process" (does that
mean in Cursive's JVM by embedding leiningen-core in it ?) ?

Asking because I'd like to avoid mirroring leiningen code when it can be
avoided...

... also, using trampoline with lein repl :headless opens the opportunity
to cache the "command line" for future usages, until invalidated by e.g.
changes to project/profile.clj, etc.

Re: [leiningen] Leiningen, Windows and process management

From:
Colin Fleming
Date:
2014-01-20 @ 13:53
That's right, although I had to do more analysis of "lein trampoline" than
"lein repl" - that's the part I had to mimic. I guess this can definitely
be classed as relying on lein internals!

One unfortunate thing with this is that you'll have to bundle all of
leiningen, not just lein core, since lein core doesn't include the task
definitions (such as repl). If you look at what trampoline does, it
essentially sets the *trampoline?* flag, then executes the task as normal,
then reads the trampoline-project/-forms/-profiles variables and creates
the trampoline script file from them. Instead of creating the script file I
just create the parameters internally in Cursive and then run the process
using IntelliJ's process infrastructure. There's a bit of messing around
but it's basically fairly simple.

I haven't investigated caching the command line since it's really not that
much work to create it, especially compared with starting up another lein
JVM.

I'm a little worried about calling lein in-process (in Cursive's JVM)
though. Leiningen is pretty clearly designed for a single-shot
task-per-invocation model, and using it in a persistent process has some
interesting side effects (see
#1378<https://github.com/technomancy/leiningen/issues/1378>),
and of course most plugins will not be written with this in mind. Another
problem is hooks (see here
<https://github.com/oakes/Nightcode/issues/56>for some info and a
potential solution - I haven't tried this yet). Plus of
course, you're essentially executing arbitrary code in your editor JVM,
which has security implications as well as loading a ton of classes.


On 20 January 2014 23:54, Laurent PETIT <laurent.petit@gmail.com> wrote:

> Hi Colin,
>
>
> 2014/1/20 Colin Fleming <colin.mailinglist@gmail.com>
>
>> Trampoline can definitely be used with "lein repl :headless", that's what
>> Cursive is currently doing to start its Leiningen-based REPLs. I call the
>> trampoline code in-process, then use the trampoline parameters to create
>> the REPL process directly rather than creating the trampoline script. I
>> call (leiningen.repl/repl project ":headless"), setting the
>> leiningen.trampoline/*trampoline?* flag to true, and then use
>> leiningen.core.eval/trampoline-project/-forms/-profiles to build my command
>> line.
>>
>
> Thanks for sharing the information!
>
> Does that mean that you did some analysis of what is done when "lein rel
> :headless" is generally invoked in a "black-box" manner from the
> command-line, and that you re-do the same think "in-process" (does that
> mean in Cursive's JVM by embedding leiningen-core in it ?) ?
>
> Asking because I'd like to avoid mirroring leiningen code when it can be
> avoided...
>
> ... also, using trampoline with lein repl :headless opens the opportunity
> to cache the "command line" for future usages, until invalidated by e.g.
> changes to project/profile.clj, etc.
>
>

Re: [leiningen] Leiningen, Windows and process management

From:
Laurent Petit
Date:
2014-01-20 @ 14:03
Hi again,


2014/1/20 Colin Fleming <colin.mailinglist@gmail.com>

> That's right, although I had to do more analysis of "lein trampoline" than
> "lein repl" - that's the part I had to mimic. I guess this can definitely
> be classed as relying on lein internals!
>
> One unfortunate thing with this is that you'll have to bundle all of
> leiningen, not just lein core, since lein core doesn't include the task
> definitions (such as repl). If you look at what trampoline does, it
> essentially sets the *trampoline?* flag, then executes the task as normal,
> then reads the trampoline-project/-forms/-profiles variables and creates
> the trampoline script file from them. Instead of creating the script file I
> just create the parameters internally in Cursive and then run the process
> using IntelliJ's process infrastructure. There's a bit of messing around
> but it's basically fairly simple.
>

Yeah, I also had to bundle the whole lein and not only leiningen-core.
Don't know if it was for the repl stuff or lein-new stuff, but I know I had
to (and tried hard not to).


>
> I haven't investigated caching the command line since it's really not that
> much work to create it, especially compared with starting up another lein
> JVM.
>

Sure, but see below ...


>
> I'm a little worried about calling lein in-process (in Cursive's JVM)
> though. Leiningen is pretty clearly designed for a single-shot
> task-per-invocation model, and using it in a persistent process has some
> interesting side effects (see 
#1378<https://github.com/technomancy/leiningen/issues/1378>),
> and of course most plugins will not be written with this in mind. Another
> problem is hooks (see here 
<https://github.com/oakes/Nightcode/issues/56>for some info and a 
potential solution - I haven't tried this yet). Plus of
> course, you're essentially executing arbitrary code in your editor JVM,
> which has security implications as well as loading a ton of classes.
>

I'm also worried about that. It has bitten me in the past: CCW uses "lein
new" and allows the user to specify arbitrary lein-newnew templates. And it
happens that when the user was wrong in typing a template name, what
lein-newnew does is call leiningen.core/abort which does a (System/exit 0) !
This is clearly again the manifestation that at its core lein is still
oriented towards quickly executing a task then exiting.
Or at least, that plugin writers program towards its API with this mindset.

So I think that I will not try too hard to fight this fact in the future,
and instead invoke lein externally. I may well end up not having neither
leiningen-standalone.jar nor leiningen-core.jar embedded in CCW at some
point in the future.

... and that's where caching the command line might come in handy !

Sure, there will be more delay e.g. when CCW notices a change to
project.clj and recomputes the classpath for Eclipse. Currently, it's
really fast (if the deps are already in the local cache). After this
change, it will be longer. But I'm okay to sacrifice a little bit in favor
of code simplicity and a more reliable IDE. Time will tell....

Re: [leiningen] Leiningen, Windows and process management

From:
Colin Fleming
Date:
2014-01-20 @ 21:36
Yeah, those commands should be calling exit, not abort, which allows you to
control whether it actually exits or not using
leiningen.core.main/*exit-process?*. I guess you could always hook abort
and make it throw an exception but it starts getting pretty messy - I'm
already hooking about 4 functions every time I call into lein.


On 21 January 2014 03:03, Laurent PETIT <laurent.petit@gmail.com> wrote:

> Hi again,
>
>
> 2014/1/20 Colin Fleming <colin.mailinglist@gmail.com>
>
>> That's right, although I had to do more analysis of "lein trampoline"
>> than "lein repl" - that's the part I had to mimic. I guess this can
>> definitely be classed as relying on lein internals!
>>
>> One unfortunate thing with this is that you'll have to bundle all of
>> leiningen, not just lein core, since lein core doesn't include the task
>> definitions (such as repl). If you look at what trampoline does, it
>> essentially sets the *trampoline?* flag, then executes the task as normal,
>> then reads the trampoline-project/-forms/-profiles variables and creates
>> the trampoline script file from them. Instead of creating the script file I
>> just create the parameters internally in Cursive and then run the process
>> using IntelliJ's process infrastructure. There's a bit of messing around
>> but it's basically fairly simple.
>>
>
> Yeah, I also had to bundle the whole lein and not only leiningen-core.
> Don't know if it was for the repl stuff or lein-new stuff, but I know I had
> to (and tried hard not to).
>
>
>>
>> I haven't investigated caching the command line since it's really not
>> that much work to create it, especially compared with starting up another
>> lein JVM.
>>
>
>  Sure, but see below ...
>
>
>>
>> I'm a little worried about calling lein in-process (in Cursive's JVM)
>> though. Leiningen is pretty clearly designed for a single-shot
>> task-per-invocation model, and using it in a persistent process has some
>> interesting side effects (see 
#1378<https://github.com/technomancy/leiningen/issues/1378>),
>> and of course most plugins will not be written with this in mind. Another
>> problem is hooks (see here 
<https://github.com/oakes/Nightcode/issues/56>for some info and a 
potential solution - I haven't tried this yet). Plus of
>> course, you're essentially executing arbitrary code in your editor JVM,
>> which has security implications as well as loading a ton of classes.
>>
>
> I'm also worried about that. It has bitten me in the past: CCW uses "lein
> new" and allows the user to specify arbitrary lein-newnew templates. And it
> happens that when the user was wrong in typing a template name, what
> lein-newnew does is call leiningen.core/abort which does a (System/exit 0) !
> This is clearly again the manifestation that at its core lein is still
> oriented towards quickly executing a task then exiting.
> Or at least, that plugin writers program towards its API with this mindset.
>
> So I think that I will not try too hard to fight this fact in the future,
> and instead invoke lein externally. I may well end up not having neither
> leiningen-standalone.jar nor leiningen-core.jar embedded in CCW at some
> point in the future.
>
> ... and that's where caching the command line might come in handy !
>
> Sure, there will be more delay e.g. when CCW notices a change to
> project.clj and recomputes the classpath for Eclipse. Currently, it's
> really fast (if the deps are already in the local cache). After this
> change, it will be longer. But I'm okay to sacrifice a little bit in favor
> of code simplicity and a more reliable IDE. Time will tell....
>

Re: [leiningen] Leiningen, Windows and process management

From:
Phil Hagelberg
Date:
2014-02-06 @ 18:33
Laurent PETIT writes:

> So I have replaced abort with my own, which directly throws an ex-info
> keeping the message.
>
> Maybe Leiningen exit could be modified to take optional message arguments,
> and abort could pass its message arguments to exit, which, in the "throw"
> case, could add an :error-message key to the ex-info ?

Yes, that would be much better. Happy to take a patch for that.

-Phil

Re: Leiningen, Windows and process management

From:
Laurent Petit
Date:
2014-02-06 @ 18:51
Le jeudi 6 février 2014, Phil Hagelberg <phil@hagelb.org> a écrit :

>
> Laurent PETIT writes:
>
> > So I have replaced abort with my own, which directly throws an ex-info
> > keeping the message.
> >
> > Maybe Leiningen exit could be modified to take optional message
> arguments,
> > and abort could pass its message arguments to exit, which, in the "throw"
> > case, could add an :error-message key to the ex-info ?
>
> Yes, that would be much better. Happy to take a patch for that.


Yes sir, will be happy to do that ASAP



>
> -Phil
>

Re: [leiningen] Re: Leiningen, Windows and process management

From:
Colin Fleming
Date:
2014-02-06 @ 21:34
BTW what I'm doing right now in that case is capturing *out* and *err*, and
in the case that I catch the abort exception I show it all to the user. It
works pretty well, and looks like this:
https://github.com/cursiveclojure/cursive/issues/122#issuecomment-29259144


On 7 February 2014 07:51, Laurent PETIT <laurent.petit@gmail.com> wrote:

>
>
> Le jeudi 6 février 2014, Phil Hagelberg <phil@hagelb.org> a écrit :
>
>
>> Laurent PETIT writes:
>>
>> > So I have replaced abort with my own, which directly throws an ex-info
>> > keeping the message.
>> >
>> > Maybe Leiningen exit could be modified to take optional message
>> arguments,
>> > and abort could pass its message arguments to exit, which, in the
>> "throw"
>> > case, could add an :error-message key to the ex-info ?
>>
>> Yes, that would be much better. Happy to take a patch for that.
>
>
> Yes sir, will be happy to do that ASAP
>
>
>
>>
>> -Phil
>>
>