On Thu, 8 Jan 2004, Alan Ruttenberg wrote:
On Jan 8, 2004, at 11:07 AM, Luke Gorrie wrote:
How will you interrupt a specific thread in OpenMCL? Do they each have their own OS PID such that you could SIGINT the right one, or is it necessary to do a (interrupt-thread T) sort of call inside Lisp? (I think the first will work in SBCL and the second will be needed in CMUCL).
Whether threads have PIDs or not depends on the OS's notion of what a thread is; on Linux they do (and Linux is gradually moving towards the realization that not all PIDs are created equal); on OSX, threads are primitive objects in the Mach kernel.
PROCESS-INTERRUPT in OpenMCL is implemented in terms of pthread_kill() with a distinguished signal number; under Linux, pthread_kill() happens to be implemented in terms of kill() sent to the pthread's PID. However it's implemented, the signal was targeted to a specific thread and the handler for that signal runs on that thread.
Openmcl only knows which thread to interrupt through a global variable that is checked during the housekeeping routine that notices that there was an interrupt. In the one repl world I was setting that variable when the connection was being opened.
SIGINT (from the keyboard or via kill()) is generally delivered to an OS process; when threads are involved, that generally means that the SIGINT handler runs on some arbitrary thread in the process (pretty much any thread that the OS feels like sending it to, as long as the thread doesn't mask SIGINT.) The global variable Alan mentions is used by lisp code that notices a recent SIGINT, so SIGINT is interpreted as an IPC request to the "OS process as a whole" to interrupt what it deems to be the most appropriate thread. (Clearly, the correct implementation of SIGINT is "interrupt the thread that the user thinks it will", and the global variable's just a way of crudlely approximating the right thread.)
Asynchronous signals tend not to carry much information; it's not clear that we could use them to implement IPC requests that asked another OS process to interrupt a specific thread. I'm not sure what kind of IPC mechanisms SWANK/SLIME already provide that might deal with the "OS process as a whole", but the lisp side of it could just involve a thread that listens for IPC requests over a socket that's created when SLIME first starts the lisp OS process. Or something.
(defvar *slime-control-socket* ... "created when SLIME starts the OS process")
(defun slime-control-loop () (loop (multiple-value-bind (request-type request-data) (read-slime-ipc-request *slime-control-socket*) (case request-type (:process-interrupt (ccl:process-interrupt (ccl:find-thread request-data) #'(lambda () ...))) (t (error "This mechanism may be overkill ..."))))))
Gary Byers gb@clozure.com