X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fwarm-mswin.lisp;h=ab43e3169a9ce6da263206e15c89ccaeff8000d8;hb=cee8ef591040db9a79cdd19297867672a9529051;hp=eef4e56e7220f1aa427044d7fedef9bffc8c2b93;hpb=ed1910efb36f71b5ebe33b5ffffd7195e15644de;p=sbcl.git diff --git a/src/code/warm-mswin.lisp b/src/code/warm-mswin.lisp index eef4e56..ab43e31 100644 --- a/src/code/warm-mswin.lisp +++ b/src/code/warm-mswin.lisp @@ -67,8 +67,8 @@ (define-alien-routine ("GetExitCodeThread" get-exit-code-thread) int (handle handle) (exit-code dword :out)) -(defun mswin-spawn (program argv stdin stdout stderr searchp envp waitp) - (declare (ignorable envp)) +(defun mswin-spawn (program argv stdin stdout stderr searchp envp waitp + directory) (let ((std-handles (multiple-value-list (get-std-handles))) (inheritp nil)) (flet ((maybe-std-handle (arg) @@ -93,7 +93,7 @@ (if (create-process (if searchp nil program) argv nil nil - inheritp 0 nil nil + inheritp 0 envp directory (alien-sap startup-info) (alien-sap process-information)) (let ((child (slot process-information 'process-handle))) @@ -104,3 +104,65 @@ (if got code -1)))) child)) -2)))))) + +(define-alien-routine ("SetConsoleCtrlHandler" set-console-ctrl-handler) int + (callback (function (:stdcall int) int)) + (enable int)) + +(defun windows-console-control-handler (event-code) + (case event-code + (0 + (flet ((interrupt-it () + (let* ((context + (sb-di::nth-interrupt-context + (1- sb-kernel:*free-interrupt-context-index*))) + (pc (sb-vm:context-pc context))) + (with-interrupts + (let ((int (make-condition + 'interactive-interrupt + :context context + :address (sb-sys:sap-int pc)))) + ;; First SIGNAL, so that handlers can run. + (signal int) + (%break 'sigint int)))))) + (sb-thread:interrupt-thread (sb-thread::foreground-thread) + #'interrupt-it) + t)))) + +(defvar *console-control-handler* #'windows-console-control-handler) +(defvar *console-control-enabled* nil) +(defvar *console-control-spec* nil) + +(sb-alien::define-alien-callback *alien-console-control-handler* (:stdcall int) + ((event-code int)) + (if (ignore-errors (funcall *console-control-handler* event-code)) 1 0)) + +(defun console-control-handler () + "Get or set windows console control handler. + +Boolean value: use default handler (NIL) or ignore event (T). Symbol +or function: designator for a function that receives an event code and +returns generalized boolean (false to fall back to other handlers, +true to stop searching)." *console-control-spec*) + +(defun (setf console-control-handler) (new-handler) + (etypecase new-handler + (boolean + (aver (plusp (set-console-ctrl-handler + (sap-alien (int-sap 0) + (function (:stdcall int) int)) + (if new-handler 1 0)))) + (setf *console-control-enabled* nil)) + ((or symbol function) + (setf *console-control-handler* new-handler) + (aver (plusp (set-console-ctrl-handler *alien-console-control-handler* 1))))) + (setf *console-control-spec* new-handler)) + +(defun initialize-console-control-handler (&optional reset-to-default-p) + (setf (console-control-handler) + (if reset-to-default-p + 'windows-console-control-handler + (console-control-handler)))) + +(initialize-console-control-handler t) +(pushnew 'initialize-console-control-handler sb-ext:*init-hooks*)