On 28/02/2022 8:20 am, Ethan McCue wrote:
My understanding is that when you System.exit all threads associated with the JVM process are killed. That's what I meant by "nuclear Thread.interrupt".

The process is terminated, the threads are not individually "killed". All Thread.interrupt does is set a flag and unpark blocked threads (in some specific cases). There's really no comparison at all.

David
-----

It's the same issue as was raised about System.exit implicitly ending control flow or implicitly closing open file handles - a process could be relying on the behavior of implicitly killing all threads and not have another cleanup mechanism

On Sun, Feb 27, 2022, 5:16 PM David Holmes <david.hol...@oracle.com <mailto:david.hol...@oracle.com>> wrote:

    On 28/02/2022 3:20 am, Ethan McCue wrote:
     > I think continuations could work for the single threaded case,
    depending on
     > their behavior with "finally" blocks. I'm sure there are more
    caveats once
     > we add another thread to the mix though. System.exit is a nuclear
     > Thread.interrupt, so replicating that behavior might be a bit
    daunting

    What has Thread.interrupt got to do with System.exit ?

    David

     >      private static final class ExitCode {
     >          volatile Integer code = null;
     >      }
     >
     >      private final ScopeLocal<ExitCode> EXIT_CODE =
    ScopeLocal.newInstance();
     >
     >      public void overridingExitBehavior(IntConsumer exit,
    Runnable run) {
     >          var exitCode = new ExitCode();
     >          ScopeLocal.with(EXIT_CODE, exitCode).run(() -> {
     >              // by whatever syntax
     >              var _ = inContinuation(run);
     >              if (exitCode.code != null) {
     >                  exit.accept(code.exitCode)
     >              }
     >          });
     >      }
     >
     >      public void exit(int status) {
     >          if (EXIT_CODE.isBound()) {
     >               EXIT_CODE.get().code = status;
     >               Continuation.yield();
     >          }
     >          else {
     >              Shutdown.exit(status);
     >          }
     >      }
     >
     >
     >
     > On Sun, Feb 27, 2022 at 10:41 AM Glavo <zjx001...@gmail.com
    <mailto:zjx001...@gmail.com>> wrote:
     >
     >> I think there is a problem with this: `System.exit` contains
    semantics to
     >> interrupt the flow of control and exit, and if you implement it
    that way,
     >> you might have some program abnormally execute parts of it that
    should
     >> never be executed.
     >>
     >> Of course, using exceptions like this should solve part of the
    problem:
     >>
     >> class Exit extends Error {
     >>      final int exitCode;
     >>      public Exit(int exitCode) {
     >>          this.exitCode = exitCode;
     >>      }
     >>
     >>      @Override
     >>      public synchronized Throwable fillInStackTrace() {
     >>          return this;
     >>      }
     >> }
     >>
     >> try {
     >>    Runtime.getRuntime().overridingExitBehavior(exitCode ->
    {throw new
     >> Exit(exitCode);}, ...);
     >> } catch (Exit exit) {
     >>    ...
     >> }
     >>
     >> However, the calling method may catch this exception
    unexpectedly, and
     >> there may be unexpected behavior under multithreading.
     >> Of course, this part of the problem also exists for the security
    manager.
     >> But, if possible, it would be better to have a solution for these
     >> situations.
     >> (`Continuation` might help us?)
     >>
     >>
     >>
     >> On Sun, Feb 27, 2022 at 11:07 PM Ethan McCue <et...@mccue.dev
    <mailto:et...@mccue.dev>> wrote:
     >>
     >>> That undermines my point some, but I think the overall shape of
    the use
     >>> case still makes sense
     >>>
     >>> On Sun, Feb 27, 2022 at 8:01 AM Remi Forax <fo...@univ-mlv.fr
    <mailto:fo...@univ-mlv.fr>> wrote:
     >>>
     >>>> Hi Ethan,
     >>>> there is a far simpler solution, call org.apache.ivy.run(args,
    true)
     >>>> instead of org.apache.ivy.main(args) in your tool provider.
     >>>>
     >>>> regards,
     >>>> Rémi
     >>>>
     >>>> ----- Original Message -----
     >>>>> From: "Ethan McCue" <et...@mccue.dev <mailto:et...@mccue.dev>>
     >>>>> To: "core-libs-dev" <core-libs-dev@openjdk.java.net
    <mailto:core-libs-dev@openjdk.java.net>>
     >>>>> Sent: Saturday, February 26, 2022 11:14:19 PM
     >>>>> Subject: Should System.exit be controlled by a Scope Local?
     >>>>
     >>>>> I have a feeling this has been considered and I might just be
     >>>> articulating
     >>>>> the obvious - but:
     >>>>>
     >>>>> As called out in JEP 411, one of the remaining legitimate
    uses of the
     >>>>> Security Manager is to intercept calls to System.exit. This seems
     >>> like a
     >>>>> decent use case for the Scope Local mechanism.
     >>>>>
     >>>>>
     >>>>>     public class Runtime {
     >>>>>         ...
     >>>>>         private final ScopeLocal<IntConsumer> EXIT =
     >>>>> ScopeLocal.newInstance();
     >>>>>
     >>>>>         ...
     >>>>>
     >>>>>         public void overridingExitBehavior(IntConsumer exit,
    Runnable
     >>>> run) {
     >>>>>             ScopeLocal.with(EXIT, exit).run(run);
     >>>>>         }
     >>>>>
     >>>>>         ...
     >>>>>
     >>>>>         public void exit(int status) {
     >>>>>             if (EXIT.isBound()) {
     >>>>>                 EXIT.get().accept(status);
     >>>>>             }
     >>>>>             else {
     >>>>>                 Shutdown.exit(status);
     >>>>>             }
     >>>>>         }
     >>>>>     }
     >>>>>
     >>>>>
     >>>>> One of the likely minor benefits in the scope of things, but
    related
     >>> to
     >>>> the
     >>>>> parts of the ecosystem I am doodling with so I'll mention it,
    is that
     >>> it
     >>>>> would become possible to wrap "naive" cli programs with the
     >>> ToolProvider
     >>>>> SPI without rewriting their code if this System.out, and
    System.err
     >>> all
     >>>>> became reliably configurable.
     >>>>>
     >>>>> For instance, Apache Ivy's CLI has a main class that looks
    like this
     >>>>>
     >>>>>
     >>>>
     >>>
    
https://github.com/apache/ant-ivy/blob/424fa89419147f50a41b4bdc665d8ea92b5da516/src/java/org/apache/ivy/Main.java
    
<https://github.com/apache/ant-ivy/blob/424fa89419147f50a41b4bdc665d8ea92b5da516/src/java/org/apache/ivy/Main.java>
     >>>>>
     >>>>>     package org.apache.ivy;
     >>>>>
     >>>>>     public final class Main {
     >>>>>         ...
     >>>>>
     >>>>>         public static void main(String[] args) throws Exception {
     >>>>>             try {
     >>>>>                 run(args, true);
     >>>>>                 System.exit(0);
     >>>>>             } catch (ParseException ex) {
     >>>>>                 System.err.println(ex.getMessage());
     >>>>>                 System.exit(1);
     >>>>>             }
     >>>>>         }
     >>>>>      }
     >>>>>
     >>>>> Making these otherwise static parts of the system
    configurable would
     >>>> enable
     >>>>> a third party library to write
     >>>>>
     >>>>>     public final class IvyToolProvider implements ToolProvider {
     >>>>>         @Override
     >>>>>         public String name() {
     >>>>>             return "ivy";
     >>>>>         }
     >>>>>
     >>>>>         @Override
     >>>>>         public int run(PrintWriter out, PrintWriter err,
    String...
     >>> args) {
     >>>>>             var exit = new AtomicInteger(0);
>>>>>  Runtime.getRuntime().overridingExitBehavior(exit::set, ()
     >>> -> {
     >>>>>                 System.overridingOut(out, () -> {
     >>>>>                      System.overridingErr(err, Main::main);
     >>>>>                 }
     >>>>>             };
     >>>>>             return exit.get();
     >>>>>         }
     >>>>>     }
     >>>>>
     >>>>> Whether that would be enough to make it so that people other than
     >>>> Christian
     >>>>> Stein use the mechanism is anyone's guess, but might be worth
    a shot.
     >>>>>
     >>>>> https://grep.app/search?q=java.util.spi.ToolProvider
    <https://grep.app/search?q=java.util.spi.ToolProvider>
     >>>>
     >>>
     >>

Reply via email to