2 ;;; This is inter-process communication support for MAXIMA.
4 ;;; The main idea is copied from gcl/maxima. We have a library
5 ;;; winkill_lib.dll which sets up a shared memory file mapping.
6 ;;; The program winkill.exe writes interrupts into the shared memory.
7 ;;; Maxima should then regularly check this memory to see if it
8 ;;; should interrupt current computation or terminate. Other
9 ;;; signals are not supported yet.
11 ;;; Currently there is only support for ccl and sbcl. Should add
12 ;;; support for all lisps other than gcl which run on windows.
19 ;; The main maxima thread
20 (defvar *main-maxima-process
*)
21 (defvar *signal-monitor-process
*)
23 (defun load-library ()
24 (ccl:open-shared-library
"winkill_lib")
25 (ccl:external-call
"init_shared_memory"))
27 (defvar *run-monitor
* nil
)
29 (defun monitor-shared-memory ()
30 (loop while
*run-monitor
* do
31 ;; Check for SIGINT signals
32 (when (= 1 (ccl:external-call
"read_sm_sigint" :int
))
33 (ccl:external-call
"reset_sm_sigint")
34 (ccl:process-interrupt
*main-maxima-process
* #'(lambda () (error "interrupt signal"))))
35 ;; Check for SIGTERM signals
36 (when (= 1 (ccl:external-call
"read_sm_sigterm" :int
))
37 (ccl:external-call
"reset_sm_sigterm")
38 (ccl:process-interrupt
*main-maxima-process
* #'(lambda () ($quit
))))
42 ;; Starts the monitor thread
43 (defun start-monitor ()
44 (setq *run-monitor
* t
)
45 (setq *main-maxima-process
* ccl
:*current-process
*)
46 (setq *signal-monitor-process
* (ccl:process-run-function
"monitor" #'monitor-shared-memory
)))
49 (when *signal-monitor-process
*
50 (ccl:process-kill
*signal-monitor-process
*))
53 (defun start-shared-memory-monitor ()
59 (sb-alien:load-shared-object
"winkill_lib.dll")
61 (defun load-library ()
62 (sb-alien:alien-funcall
(sb-alien:extern-alien
"init_shared_memory" (sb-alien:function sb-alien
:void
))))
64 (defvar *run-monitor
* nil
)
66 (defun monitor-shared-memory ()
67 (loop while
*run-monitor
* do
68 ;; Check for SIGINT signals
69 (when (= 1 (sb-alien:alien-funcall
(sb-alien:extern-alien
"read_sm_sigint" (sb-alien:function sb-alien
:int
))))
70 (sb-alien:alien-funcall
(sb-alien:extern-alien
"reset_sm_sigint" (function sb-alien
:void
)))
71 (sb-thread:interrupt-thread
(sb-thread:main-thread
) #'(lambda () (error "interrupt signal"))))
72 ;; Check for SIGTERM signals
73 (when (= 1 (sb-alien:alien-funcall
(sb-alien:extern-alien
"read_sm_sigterm" (sb-alien:function sb-alien
:int
))))
74 (sb-alien:alien-funcall
(sb-alien:extern-alien
"reset_sm_sigterm" (sb-alien:function sb-alien
:void
)))
75 (sb-thread:interrupt-thread
(sb-thread:main-thread
) #'(lambda () ($quit
))))
79 ;; Starts the monitor thread
80 (defun start-monitor ()
81 (setq *run-monitor
* t
)
82 (sb-thread:make-thread
#'monitor-shared-memory
:name
"monitor"))
84 (defun start-shared-memory-monitor ()
90 (defun start-shared-memory-monitor ())
93 ;; This function should be called when Maxima starts.
94 (start-shared-memory-monitor)