Unix信号处理(通用)lisp

Unix信号处理(通用)lisp,lisp,common-lisp,signals,sigint,ccl,Lisp,Common Lisp,Signals,Sigint,Ccl,我在这个问题上做了一些研究,现在发现了一些空白。在Common Lisp中似乎有一些依赖于实现的Unix信号处理方法,但是否有一个包提供了一种跨实现的信号处理方法 我主要想听听SIGINT,然后在我的应用程序中优雅地关机。我在linux上使用Clozure CL 1.7…就像前面提到的,这对于一个包来说是很好的,但是如果我必须使用特定于实现的代码,那就好了 我还没有完全同意使用SIGINT(尽管它很理想)。如果需要,我可以使用另一个信号 如果这将是混乱的,有没有人对从应用程序外部优雅地关闭lis

我在这个问题上做了一些研究,现在发现了一些空白。在Common Lisp中似乎有一些依赖于实现的Unix信号处理方法,但是否有一个包提供了一种跨实现的信号处理方法

我主要想听听SIGINT,然后在我的应用程序中优雅地关机。我在linux上使用Clozure CL 1.7…就像前面提到的,这对于一个包来说是很好的,但是如果我必须使用特定于实现的代码,那就好了

我还没有完全同意使用SIGINT(尽管它很理想)。如果需要,我可以使用另一个信号

如果这将是混乱的,有没有人对从应用程序外部优雅地关闭lisp应用程序有任何其他建议?我的一个想法是创建一个应用程序监视的文件,如果它检测到该文件,它就会关闭……尽管有点黑客


谢谢

我也找不到用于信号处理的通用库。但是,对于大多数Lisp实现,实现了“创建自定义
SIGINT
handler”。通过查看该代码的CCL案例,我发现
CCL:*断钩*
<代码>ccl:*break hook*不在文档中,但它引入的提交位于

这个简单的示例代码适用于我的系统(CCL1.8,linux x86):


将此代码输入非粘液回复后,发送
SIGINT
将导致程序打印“清理…”并退出

尽管出于无知,我最初对Daimrod关于使用CFFI的评论(问题下的第一个评论)表示怀疑,但我四处看了看,发现了更多。我将其调整为使用CFFI,并确认在linux上的SBCL/CCL/clisp(可能是其他)上工作得非常好:

(defmacro set-signal-handler (signo &body body)
  (let ((handler (gensym "HANDLER")))
    `(progn
       (cffi:defcallback ,handler :void ((signo :int))
         (declare (ignore signo))
         ,@body)
       (cffi:foreign-funcall "signal" :int ,signo :pointer (cffi:callback ,handler)))))

(set-signal-handler 2
  (format t "Quitting lol!!!11~%")
  ;; fictional function that lets the app know to quit cleanly (don't quit from callback)
  (signal-app-to-quit))
请注意,据我所知,回调函数体中的任何内容都必须简短而甜美!无需长时间处理。在链接的文章中,宏实际上创建了一个单独的线程来处理信号,这对于我来说太过分了,因为我只是将一个全局变量从
nil
设置为
t
并返回


无论如何,希望这对其他人有帮助

这是一个迟来的答案,但对于其他搜索此答案的人,请查看Quicklisp上提供的。这是基于CFFI的

例子
如果使用SBCL,则无法在不导致SBCL崩溃的情况下更改信号掩码。询问nyef关于如何修复SBCL的提示…

您尝试过吗?不,我没有尝试CFFI,我正在寻找更多通过ASDF提供的库,该库将对此进行抽象。我认为(对我来说)用C创建一个跨实现的unix信号处理程序并为其编写一个CFFI包装器可能比它的价值更麻烦……特别是因为我从未编写过C API。“我不反对这样做,但我现在真的没有时间这么做。”戴姆罗德:你的建议让我想得更多。看看下面我的答案。当我看到您的评论时,我不知道不制作整个包装器库就可以处理unix信号。您可以调用
signal
C函数直接从CFFI替换信号处理程序。SLIM的“创建自定义SIGINT处理程序”功能在哪里?我正在尝试各种各样的子串,但没有找到它。哦,嗯,我在Slime特定的Apropos中找到了
SWANK-BACKEND:INSTALL-SIGINT-HANDLER
,但我不确定如何运行它。无论如何,如果找不到现有库的正确答案,也许我们可以收集这些答案,然后根据这个问题找出编写一个库需要什么?:)<代码>安装sigint处理程序似乎只在少数实现中实现(查看
swank-{prog name}.lisp
)。我通过查找ccl使用调试器钩子调用的代码找到了
*break hook*
。我认为一些Lisp可能没有ccl的
*break hook*
这样的机制,因此使用条件名
+
处理程序case
处理程序bind
可以提供最大的可移植性。(是的,库
琐碎的sigint
听起来是个好主意。)当我不包括ccl::quit时,它仍然会在函数运行后触发中断条件。有没有办法取消这个?基本上,我想向几个线程发出信号“嘿,该清理并很好地退出了。”那么有没有办法绑定break钩子,然后在它自动运行后继续执行?不管怎样,谢谢你找到这个,它帮助很大!如果您想这样做,您需要“跳出”程序的另一部分<代码>抛出/
捕获
,条件、重新启动或某些其他控制传输机制可能会起作用。但是,再一次,“代码> *Boox**/Cube”可能在系统调用的中间被调用,所以在退出之前不要做太多。谢谢,这看起来很有用。cl async中也有一些信号处理功能,但只有在事件循环中才起作用。对于一般信号处理,这看起来是最好的选择。
(defmacro set-signal-handler (signo &body body)
  (let ((handler (gensym "HANDLER")))
    `(progn
       (cffi:defcallback ,handler :void ((signo :int))
         (declare (ignore signo))
         ,@body)
       (cffi:foreign-funcall "signal" :int ,signo :pointer (cffi:callback ,handler)))))

(set-signal-handler 2
  (format t "Quitting lol!!!11~%")
  ;; fictional function that lets the app know to quit cleanly (don't quit from callback)
  (signal-app-to-quit))
(signal-handler-bind ((:int  (lambda (signo)
                               (declare (ignorable signo))
                               ...handler...)))
  ...body...)