我已经对这个问题进行了一些研究,并且正在填补空白。在Common Lisp中似乎存在依赖于实现的Unix信号处理方式,但是是否有一个包提供了交叉实现的信号处理方式?
我主要想听听SIGINT并在我的应用程序中正常关机。我在linux上使用Clozure CL 1.7 ...就像提到的那样,对于这个包来说会很棒,但是如果我不得不求助于特定于实现的代码,那很好。
我也没有完全嫁给使用SIGINT(尽管它是理想的)。如果需要,我可以使用另一个信号。
如果这将是混乱的,有没有人有任何其他建议优雅地从应用程序外部关闭lisp应用程序?我的一个想法是创建一个应用程序监视的文件,如果它检测到文件,它会关闭......但是有点hacky。
谢谢!
答案 0 :(得分:8)
虽然出于无知,我最初对戴姆罗德关于使用CFFI的评论(在问题下的第一条评论)持怀疑态度,但我更多地看了一下并发现了http://clozure.com/pipermail/openmcl-devel/2010-July/011675.html。我改编它使用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
并返回。 / p>
无论如何,希望这对其他人有帮助!
答案 1 :(得分:7)
我找不到用于信号处理的通用库。但是,Slime实现了“为大多数Lisp实现创建自定义SIGINT
处理程序”。通过查看该代码的CCL案例,我找到了ccl:*break-hook*
。 ccl:*break-hook*
不在文档中,但它所引入的提交位于here。
这个简单的示例代码适用于我的系统(CCL 1.8,linux x86):
(setf ccl:*break-hook*
(lambda (cond hook)
(declare (ignore cond hook))
(format t "Cleaning up ...")
(ccl:quit)))
将此代码输入非Slime REPL后,发送SIGINT
将导致程序打印“正在清理...”并退出。
答案 2 :(得分:5)
这是一个迟到的答案,但对于其他搜索此问题的人,请查看Quicklisp上提供的trivial-signal。这是基于CFFI。
(signal-handler-bind ((:int (lambda (signo)
(declare (ignorable signo))
...handler...)))
...body...)
答案 3 :(得分:1)
如果使用SBCL,则无法在不导致SBCL崩溃的情况下更改信号掩码。询问nyef关于如何修复SBCL的提示......