7

I'm playing with someone else's code by examining it in the repl.

It keeps calling System/exit, which brings down my repl. This is infuriating.

In all the code I have access to, I've mocked the calls out.

But it's also calling some library code I don't have the source to, both java and clojure, and this occasionally causes exits too.

Is there any way to catch these calls globally, so that an attempt to call them doesn't kill the repl thread? Ideally it would just throw an exception instead.

I think in java I could install a new SecurityManager to get this effect, but I've never done it

there seems to be something in that line here: http://jroller.com/ethdsy/entry/disabling_system_exit

So I'm thinking something like:

(System/setSecurityManager (SecurityManager.))

only I somehow need to attach

  public void checkPermission( Permission permission ) {
    if( "exitVM".equals( permission.getName() ) ) {
      throw new ExitTrappedException() ;
    }
  }

My best shot so far is:

(System/setSecurityManager
 (proxy [SecurityManager] []
   (checkPermission [p]
                    (when (= "exitVM" (.getName p))
                      (throw (Exception. "exit"))))))

or maybe

(System/setSecurityManager 
  (proxy [SecurityManager] [] 
    (checkExit [n] false)))

But they both just destroy the repl

Or is there a better way of doing this?

John Lawrence Aspden
  • 17,124
  • 11
  • 67
  • 110

4 Answers4

2

Use AspectJ and intercept all Calls to System.exit() with a no op.

But you are right, just configuring the security manager would be saner.

Daniel
  • 27,718
  • 20
  • 89
  • 133
  • SecurityManager - A terminally deprecated method in java.lang.System has been called. What could be a right solution for 2022? – user2305886 Apr 20 '22 at 00:25
1

This one works for me in both, Clojures simple REPL, and in the Lein REPL, too

(def SM (proxy [SecurityManager] [] 
          (checkPermission 
            [^java.security.Permission p] 
            (when (.startsWith (.getName p) "exitVM") 
              (throw (SecurityException. "exit")))))) 

(System/setSecurityManager SM)

Ah. Even in the Cider REPL in Emacs.

The name is actually "exitVM.n", where n is the numeric exit code passed to System/exit

I still have an issue to extend this security manager. Surprisingly many Clojure functions call the security manager, and thus, when used inside of it, give an infinite loop, aka StackOverflowException.

(For the latter I opened anothe question: Security Manager in Clojure )

Community
  • 1
  • 1
Falko
  • 1,028
  • 1
  • 12
  • 24
1

You can also use clj-sandbox to restrict code you don't trust.

aav
  • 2,514
  • 1
  • 19
  • 27
-1

You can try this: http://download.oracle.com/javase/6/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)

Shantanu Kumar
  • 1,240
  • 1
  • 12
  • 14