在我无法访问的代码中阻止系统/退出

时间:2011-02-11 19:38:23

标签: clojure

我正在通过在repl中检查它来玩别人的代码。

它一直调用System / exit,这会导致我的repl。这令人气愤。

在我可以访问的所有代码中,我都嘲笑了这些调用。

但它也调用了一些我没有源代码的库代码,包括java和clojure,这偶尔会导致退出。

有没有办法全局捕获这些调用,因此尝试调用它们不会杀死repl线程?理想情况下,它只会抛出异常。

我认为在java中我可以安装一个新的SecurityManager来实现这个效果,但我从来没有这样做过

这里似乎有一些东西: http://jroller.com/ethdsy/entry/disabling_system_exit

所以我想的是:

(System/setSecurityManager (SecurityManager.))

只有我需要附加

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

到目前为止,我最好的拍摄是:

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

或者

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

但他们俩都只是破坏了repl

或者有更好的方法吗?

4 个答案:

答案 0 :(得分:2)

使用AspectJ并使用no op拦截对System.exit()的所有调用。

但你是对的,只是配置安全管理器会更安全。

答案 1 :(得分:1)

您还可以使用clj-sandbox来限制您不信任的代码。

答案 2 :(得分:1)

这个对我来说既适用于Clojures简单的REPL,也适用于Lein REPL

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

(System/setSecurityManager SM)

阿。甚至在Emacs的Cider REPL中也是如此。

名称实际上是“exitVM.n”,其中n是传递给System / exit的数字退出代码

我仍有一个问题需要扩展此安全管理器。令人惊讶的是,许多Clojure函数调用安全管理器,因此,当在其中使用时,给出一个无限循环,即StackOverflowException。

(对于后者,我提出了另一个问题:Security Manager in Clojure

答案 3 :(得分:-1)