@@ -12,11 +12,8 @@ object Sandbox {
12
12
final val timeout = 3000 // TODO add a flag to allow custom timeouts
13
13
14
14
def runInSecuredThread [T ](thunk : => T ): T = {
15
- // Implementation assumes single threaded
16
- val oldSecurityManager = System .getSecurityManager
17
15
try {
18
- val securityManager = new SandboxSecurityManager
19
- System .setSecurityManager(securityManager)
16
+ val securityManager : SandboxSecurityManager = SandboxSecurityManager .init()
20
17
class SandboxThread extends Thread {
21
18
var result : scala.util.Try [T ] =
22
19
scala.util.Failure (new Exception (" Sandbox failed with a fatal error" ))
@@ -35,7 +32,33 @@ object Sandbox {
35
32
throw new InvocationTargetException (new QuoteError (s " Failed to evaluate inlined quote. Caused by timeout ( $timeout ms). " ))
36
33
} else thread.result.fold[T ](throw _, identity)
37
34
} finally {
38
- System .setSecurityManager(oldSecurityManager)
35
+ SandboxSecurityManager .stop()
36
+ }
37
+ }
38
+
39
+ object SandboxSecurityManager {
40
+ private [this ] var running = 0
41
+
42
+ private [Sandbox ] def init (): SandboxSecurityManager = synchronized {
43
+ running += 1
44
+ System .getSecurityManager match {
45
+ case securityManager : SandboxSecurityManager =>
46
+ assert(running > 1 )
47
+ securityManager
48
+ case securityManager =>
49
+ assert(running == 1 )
50
+ assert(securityManager == null )
51
+ val sandboxSecurityManager = new SandboxSecurityManager
52
+ System .setSecurityManager(sandboxSecurityManager)
53
+ sandboxSecurityManager
54
+ }
55
+ }
56
+
57
+ private [Sandbox ] def stop (): Unit = synchronized {
58
+ running -= 1
59
+ assert(System .getSecurityManager.isInstanceOf [SandboxSecurityManager ])
60
+ if (running == 0 )
61
+ System .setSecurityManager(null )
39
62
}
40
63
}
41
64
0 commit comments