Need to manage custodians better.
(module acl2-controller (lib "")
  (require (lib "")
           (lib "" "mred")
           (lib "" "framework")
           (lib "")
           (lib "" "drscheme")
           (lib "")
  (require "acl2-controller-sig.scm")
  (import ;acl2-language^
  (export acl2-controller^)
  (define (display-admit-failure-dialog parent)
    (message-box "Failed to admit definitions"
                  "ACL2 failed to admit your definitions.  To discover why, click Start ACL2 "
                  "and try admitting your definitions interactively.")
                 '(ok stop)))
  ;; This controller mediates between the DrS GUI and
  ;; an instance of acl2-process%.
  (define acl2-controller%
    (class* object% ()
      (field [acl2-process #f])
      (field [acl2-proof-window #f])
      (field [acl2-custodian #f])
      ;; Invoked when the proof console closes
      (define/public (proof-window-closed) (shutdown-acl2))
      (define/public (start-acl2 path)
        (set! acl2-custodian (make-custodian))
        (parameterize ([current-eventspace (make-eventspace)])
          (set! acl2-proof-window
                (new acl2-proof-window%
                     [parent #f]
                      (lambda () (send this proof-window-closed))])))
        (parameterize ([current-custodian acl2-custodian])
          (set! acl2-process 
                (new acl2-process% 
                     [acl2-output-port (send acl2-proof-window get-write-port)]
                     [path path]
                      (lambda (tree) 
                        (send acl2-proof-window set-proof-tree tree))]))
          (with-handlers ([exn:fail:user?
                           (lambda (e)
                             (set! acl2-proof-window #f)
                             (custodian-shutdown-all acl2-custodian)
                             (set! acl2-custodian #f)
                             (raise e))])
            (send acl2-process start!)
            (send acl2-proof-window show #t))))
      (define/public (shutdown-acl2)
        (when acl2-process 
          (send acl2-process stop!)
          (set! acl2-process #f))
        (when acl2-custodian 
          (custodian-shutdown-all acl2-custodian)
          (set! acl2-proof-window #f)
          (set! acl2-custodian #f)))
      ;; -> boolean
      ;; Produce #t if ACL2 admits the definitions window, #f otherwise.
      (define/public (admit-definitions-window dt drs-frame)
        (let ([admitted?
               (let ([exprs (send dt get-s-expressions)])
                 (if (null? exprs)
                     (send (new admit-dialog%
                                [parent drs-frame] 
                                [expressions exprs])
          (unless admitted? (display-admit-failure-dialog drs-frame))
      (define/public (admit-next dt)
        (let ([expr-str (send dt get-next-unadmitted-sexp)])
           (if (or (string-ci=? expr-str ":q")
                   (string-ci=? expr-str "(good-bye)"))
               (begin (send dt highlight-next-unadmitted-sexp #f)
                      (message-box ":q or (good-bye) found in definitions window"
                                   (format "Use the Stop Prover button to stop ACL2 instead of sending ~a via the Admit button" expr-str)
                                   #f ;drscheme-frame
                                   '(ok stop))
               (let ([admitted? (send acl2-process send-to-repl expr-str)])
                 (send dt highlight-next-unadmitted-sexp admitted?)
      (define/public (admit-all dt)
        (with-handlers ([exn:fail? void])
          (let loop ()
            (when (admit-next dt)
      (define/public (undo-all)
        (send acl2-process reset-acl2))

      (define/public (certify-book filename)
        (send acl2-process reset-acl2)
        (send acl2-process send-to-repl `(certify-book ,filename 1)))
      ;; definitions:text<%> -> void
      (define/public (undo-last dt)
        (let ([was-event-form? (send dt unhighlight-last-admitted)])
          (when was-event-form? (send acl2-process undo-last))))
      (define/public (interrupt-acl2) 
        (send acl2-process interrupt))