* Added `exn:fail:sandbox-terminated' for all sandbox termination
kinds. * The default exit handler kills the sandbox, with an appropriate termination message. * Also, sending an eof to the sandbox shows 'eof as the reason * Added some tests for these. * Still need to deal with termination messages for evaluator suicide. svn: r12837
This commit is contained in:
parent
bdf71f1b46
commit
188489b34f
|
@ -39,6 +39,8 @@
|
||||||
call-in-nested-thread*
|
call-in-nested-thread*
|
||||||
call-with-limits
|
call-with-limits
|
||||||
with-limits
|
with-limits
|
||||||
|
exn:fail:sandbox-terminated?
|
||||||
|
exn:fail:sandbox-terminated-reason
|
||||||
exn:fail:resource?
|
exn:fail:resource?
|
||||||
exn:fail:resource-resource)
|
exn:fail:resource-resource)
|
||||||
|
|
||||||
|
@ -152,8 +154,8 @@
|
||||||
'sandbox-security-guard
|
'sandbox-security-guard
|
||||||
"security-guard or a security-guard translator procedure" x)))))
|
"security-guard or a security-guard translator procedure" x)))))
|
||||||
|
|
||||||
(define (default-sandbox-exit-handler _)
|
;; this is never really used (see where it's used in the evaluator)
|
||||||
(error 'exit "sandboxed code cannot exit"))
|
(define (default-sandbox-exit-handler _) (error 'exit "sandbox exits"))
|
||||||
|
|
||||||
(define sandbox-exit-handler (make-parameter default-sandbox-exit-handler))
|
(define sandbox-exit-handler (make-parameter default-sandbox-exit-handler))
|
||||||
|
|
||||||
|
@ -516,6 +518,14 @@
|
||||||
(define-evaluator-messenger (get-uncovered-expressions . xs) 'uncovered)
|
(define-evaluator-messenger (get-uncovered-expressions . xs) 'uncovered)
|
||||||
(define-evaluator-messenger (call-in-sandbox-context thunk) 'thunk)
|
(define-evaluator-messenger (call-in-sandbox-context thunk) 'thunk)
|
||||||
|
|
||||||
|
|
||||||
|
(define-struct (exn:fail:sandbox-terminated exn:fail) (reason) #:transparent)
|
||||||
|
(define (make-terminated reason)
|
||||||
|
(make-exn:fail:sandbox-terminated
|
||||||
|
(format "evaluator: terminated (~a)" reason)
|
||||||
|
(current-continuation-marks)
|
||||||
|
reason))
|
||||||
|
|
||||||
(define (make-evaluator* init-hook allow program-maker)
|
(define (make-evaluator* init-hook allow program-maker)
|
||||||
(define orig-code-inspector (current-code-inspector))
|
(define orig-code-inspector (current-code-inspector))
|
||||||
(define orig-cust (current-custodian))
|
(define orig-cust (current-custodian))
|
||||||
|
@ -532,6 +542,12 @@
|
||||||
(define limits (sandbox-eval-limits))
|
(define limits (sandbox-eval-limits))
|
||||||
(define user-thread #t) ; set later to the thread
|
(define user-thread #t) ; set later to the thread
|
||||||
(define user-done-evt #t) ; set in the same place
|
(define user-done-evt #t) ; set in the same place
|
||||||
|
(define terminated? #f) ; set to an exception value when the sandbox dies
|
||||||
|
(define (terminated! reason)
|
||||||
|
(unless terminated?
|
||||||
|
(set! terminated?
|
||||||
|
(make-terminated ; use #f to detect internal errors
|
||||||
|
(or reason "internal error: no termination reason")))))
|
||||||
(define (limit-thunk thunk)
|
(define (limit-thunk thunk)
|
||||||
(let* ([sec (and limits (car limits))]
|
(let* ([sec (and limits (car limits))]
|
||||||
[mb (and limits (cadr limits))])
|
[mb (and limits (cadr limits))])
|
||||||
|
@ -540,6 +556,7 @@
|
||||||
(when user-thread
|
(when user-thread
|
||||||
(let ([t user-thread])
|
(let ([t user-thread])
|
||||||
(set! user-thread #f)
|
(set! user-thread #f)
|
||||||
|
(terminated! #f)
|
||||||
(custodian-shutdown-all user-cust)
|
(custodian-shutdown-all user-cust)
|
||||||
(kill-thread t))) ; just in case
|
(kill-thread t))) ; just in case
|
||||||
(void))
|
(void))
|
||||||
|
@ -560,7 +577,8 @@
|
||||||
(let ([n 0])
|
(let ([n 0])
|
||||||
(let loop ()
|
(let loop ()
|
||||||
(let ([expr (channel-get input-ch)])
|
(let ([expr (channel-get input-ch)])
|
||||||
(when (eof-object? expr) (channel-put result-ch expr) (user-kill))
|
(when (eof-object? expr)
|
||||||
|
(terminated! 'eof) (channel-put result-ch expr) (user-kill))
|
||||||
(with-handlers ([void (lambda (exn)
|
(with-handlers ([void (lambda (exn)
|
||||||
(channel-put result-ch (cons 'exn exn)))])
|
(channel-put result-ch (cons 'exn exn)))])
|
||||||
(define run
|
(define run
|
||||||
|
@ -585,9 +603,12 @@
|
||||||
(loop))])
|
(loop))])
|
||||||
(sync user-done-evt result-ch))))
|
(sync user-done-evt result-ch))))
|
||||||
eof)])
|
eof)])
|
||||||
(cond [(eof-object? r) (error 'evaluator "terminated~a"
|
(cond [(eof-object? r)
|
||||||
|
(unless terminated?
|
||||||
(if (custodian-box-value memory-cust-box)
|
(if (custodian-box-value memory-cust-box)
|
||||||
"" " (memory exceeded)"))]
|
(terminated! 'out-of-memory)
|
||||||
|
(terminated! #f)))
|
||||||
|
(raise terminated?)]
|
||||||
[(eq? (car r) 'exn) (raise (cdr r))]
|
[(eq? (car r) 'exn) (raise (cdr r))]
|
||||||
[else (apply values (cdr r))])))
|
[else (apply values (cdr r))])))
|
||||||
(define get-uncovered
|
(define get-uncovered
|
||||||
|
@ -617,7 +638,7 @@
|
||||||
(let ([msg (evaluator-message-msg expr)])
|
(let ([msg (evaluator-message-msg expr)])
|
||||||
(case msg
|
(case msg
|
||||||
[(alive?) (and user-thread (not (thread-dead? user-thread)))]
|
[(alive?) (and user-thread (not (thread-dead? user-thread)))]
|
||||||
[(kill) (user-kill)]
|
[(kill) (terminated! 'evaluator-killed) (user-kill)]
|
||||||
[(break) (user-break)]
|
[(break) (user-break)]
|
||||||
[(limits) (set! limits (evaluator-message-args expr))]
|
[(limits) (set! limits (evaluator-message-args expr))]
|
||||||
[(input) (apply input-putter (evaluator-message-args expr))]
|
[(input) (apply input-putter (evaluator-message-args expr))]
|
||||||
|
@ -687,7 +708,11 @@
|
||||||
;; restrict the sandbox context from this point
|
;; restrict the sandbox context from this point
|
||||||
[current-security-guard
|
[current-security-guard
|
||||||
(let ([g (sandbox-security-guard)]) (if (security-guard? g) g (g)))]
|
(let ([g (sandbox-security-guard)]) (if (security-guard? g) g (g)))]
|
||||||
[exit-handler (sandbox-exit-handler)]
|
[exit-handler
|
||||||
|
(let ([h (sandbox-exit-handler)])
|
||||||
|
(if (eq? h default-sandbox-exit-handler)
|
||||||
|
(lambda _ (terminated! 'exited) (user-kill))
|
||||||
|
h))]
|
||||||
[current-inspector ((sandbox-make-inspector))]
|
[current-inspector ((sandbox-make-inspector))]
|
||||||
[current-logger ((sandbox-make-logger))]
|
[current-logger ((sandbox-make-logger))]
|
||||||
[current-code-inspector (make-inspector)]
|
[current-code-inspector (make-inspector)]
|
||||||
|
|
|
@ -243,6 +243,19 @@ used from a module (by using a new namespace):
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc*[([(exn:fail:sandbox-terminated? [v any/c]) boolean?]
|
||||||
|
[(exn:fail:sandbox-terminated-reason [exn exn:fail:sandbox-terminated?])
|
||||||
|
symbol/c])]{
|
||||||
|
|
||||||
|
A predicate and accessor for exceptions that are raised when a sandbox
|
||||||
|
is terminated. Once a sandbox raises such an exception, it will
|
||||||
|
continue to raise it on further evaluation attempts.
|
||||||
|
|
||||||
|
@scheme[call-with-limits]. The @scheme[resource] field holds a symbol,
|
||||||
|
either @scheme['time] or @scheme['memory].}
|
||||||
|
|
||||||
|
|
||||||
@; ----------------------------------------------------------------------
|
@; ----------------------------------------------------------------------
|
||||||
|
|
||||||
@section{Customizing Evaluators}
|
@section{Customizing Evaluators}
|
||||||
|
@ -472,7 +485,9 @@ network connection.}
|
||||||
@defparam[sandbox-exit-handler handler (any/c . -> . any)]{
|
@defparam[sandbox-exit-handler handler (any/c . -> . any)]{
|
||||||
|
|
||||||
A parameter that determines the initial @scheme[(exit-handler)] for
|
A parameter that determines the initial @scheme[(exit-handler)] for
|
||||||
sandboxed evaluations. The default handler simply throws an error.}
|
sandboxed evaluations. The default kills the evaluator with an
|
||||||
|
appropriate error message (see
|
||||||
|
@scheme[exn:fail:sandbox-terminated-reason]).}
|
||||||
|
|
||||||
|
|
||||||
@defparam[sandbox-memory-limit limit (or/c exact-nonnegative-integer? #f)]{
|
@defparam[sandbox-memory-limit limit (or/c exact-nonnegative-integer? #f)]{
|
||||||
|
|
|
@ -130,12 +130,16 @@
|
||||||
(thread (lambda () (sleep 1) (break-evaluator ev)))
|
(thread (lambda () (sleep 1) (break-evaluator ev)))
|
||||||
--eval--
|
--eval--
|
||||||
(sleep 2) =err> "user break"
|
(sleep 2) =err> "user break"
|
||||||
|
(printf "x = ~s\n" x) => (void)
|
||||||
;; termination
|
;; termination
|
||||||
--eval--
|
--eval--
|
||||||
(printf "x = ~s\n" x) => (void)
|
,eof =err> "terminated .eof.$"
|
||||||
,eof =err> "terminated"
|
123 =err> "terminated .eof.$"
|
||||||
x =err> "terminated"
|
,eof =err> "terminated .eof.$"
|
||||||
,eof =err> "terminated"
|
|
||||||
|
;; other termination messages
|
||||||
|
--top-- (set! ev (make-evaluator 'scheme/base)) (kill-evaluator ev)
|
||||||
|
--eval-- 123 =err> "terminated .evaluator-killed."
|
||||||
|
|
||||||
;; eval-limits apply to the sandbox creation too
|
;; eval-limits apply to the sandbox creation too
|
||||||
--top--
|
--top--
|
||||||
|
@ -198,9 +202,9 @@
|
||||||
--top--
|
--top--
|
||||||
(kill-evaluator ev) => (void)
|
(kill-evaluator ev) => (void)
|
||||||
--eval--
|
--eval--
|
||||||
x =err> "terminated"
|
x =err> "terminated .evaluator-killed."
|
||||||
y =err> "terminated"
|
y =err> "terminated .evaluator-killed."
|
||||||
,eof =err> "terminated"
|
,eof =err> "terminated .evaluator-killed."
|
||||||
--top--
|
--top--
|
||||||
(let-values ([(i1 o1) (make-pipe)] [(i2 o2) (make-pipe)])
|
(let-values ([(i1 o1) (make-pipe)] [(i2 o2) (make-pipe)])
|
||||||
;; o1 -> i1 -ev-> o2 -> i2
|
;; o1 -> i1 -ev-> o2 -> i2
|
||||||
|
|
Loading…
Reference in New Issue
Block a user