(普通)lisp中的Unix信号处理

时间:2012-03-30 21:33:03

标签: lisp common-lisp signals sigint ccl

我已经对这个问题进行了一些研究,并且正在填补空白。在Common Lisp中似乎存在依赖于实现的Unix信号处理方式,但是是否有一个包提供了交叉实现的信号处理方式?

我主要想听听SIGINT并在我的应用程序中正常关机。我在linux上使用Clozure CL 1.7 ...就像提到的那样,对于这个包来说会很棒,但是如果我不得不求助于特定于实现的代码,那很好。

我也没有完全嫁给使用SIGINT(尽管它是理想的)。如果需要,我可以使用另一个信号。

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

谢谢!

4 个答案:

答案 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的提示......