Some background. Following SBCL we have fully supported process-kill and process-interrupt using signal handlers. However POSIX demands various things from a signal handler. One is that it should do very little. It is not allowed to call almost any function:
Currently we do not follow this document. When a signal is delivered to a thread one of three things happen
1* the signal is queued (forces periodic checks for interrupts)
2* control is automatically transferred to an outer error handler (longjmp)
3* a lisp error handler is executed from the signal handler
The last two are obviously non-POSIX compliant.
For me there is no satisfactory solution so far. A possible extension we tried once is
3b* suspend the thread and execute the error handler in a separate thread
However this still does not solve an important problem: how do we handle functions that lock a thread and for which it is not safe to use signals. I am currently thinking of mp:get-lock, but there are a variety of other functions, C or Lisp, external or internal. These are functions that contradict user's expectations:
* It is not safe to interrupt them
* Yet they may cause a thread to run forever.
I believe all these problems arise from Common Lisp's users expectations, for which the language should provide the flexibility of an interpreted environment, and also in the implementations themselves, for which the multithreading API is in many cases still rooted on preemptive multithreading paradigms. However, in many other programming environments (Java, Python, C, ...) thread cancellation and interrupts either have been strongly deprecated, very much restricted or simply do not exist.
My question is whether it should be possible to live in a Lisp implementation that has no interrupts, allows suspending a thread, allows queueing signals between threads, explicit checks for the presence of those signals and finally, as a last resort, killing a thread (pthread_cancel), but knowing that this may or may not leave the implementation in a sane status. Ctrl-C would still work, in a sense, as it does now: it spawns a new thread from which we may operate with the environment, performing the previous tasks. It would also do its job, sometimes, as when the implementation awaits input: in that case sending a Unix signal stops the I/O routine safely.
I also welcome whatever feedback you may have regarding these problems.