Обработка сигналов Unix в (общем) lisp - PullRequest
11 голосов
/ 31 марта 2012

Я провел небольшое исследование по этому вопросу, и я получаю пробелы. Похоже, что в Common Lisp есть способы реализации обработки Unix-сигналов, зависящие от реализации, но есть ли пакет, который дает способ кросс-реализации для обработки сигналов?

Я бы в основном хотел послушать SIGINT и сделать аккуратное завершение работы моего приложения. Я использую Clozure CL 1.7 в Linux ... как уже упоминалось, это было бы замечательно для пакета для этого, но если мне придется прибегнуть к специфичному для реализации коду, это нормально.

Я также не совсем женат на использовании SIGINT (хотя это идеально). Я могу использовать другой сигнал, если это необходимо.

Если это будет грязно, есть ли у кого-нибудь еще предложения по изящному закрытию приложения lisp из-за пределов приложения? У меня была одна идея - создать файл, за которым следит приложение, и, если он обнаружит файл, он закроется ... хотя и немного хакерский.

Спасибо!

Ответы [ 4 ]

8 голосов
/ 04 мая 2012

Хотя по незнанию я изначально скептически относился к комментарию Даймрода (первый комментарий под вопросом) об использовании CFFI, я немного осмотрелся и обнаружил, http://clozure.com/pipermail/openmcl-devel/2010-July/011675.html. я адаптировал его для использования CFFI и подтвердил эту работуна SBCL / CCL / clisp (возможно, на других) на linux чертовски хорошо:

(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 и возвращаю.

Во всяком случае, надеюсь, это полезно для других!

7 голосов
/ 31 марта 2012

Я также не могу найти общую библиотеку для обработки сигналов.Однако Slime реализует «создание собственного обработчика SIGINT» для большинства реализаций Lisp.Глядя на случай CCL этого кода, я нашел ccl:*break-hook*.ccl:*break-hook* отсутствует в документации, но коммит, в котором он был представлен, находится здесь .

Этот простой пример кода работает на моей системе (CCL 1.8, linux x86):

(setf ccl:*break-hook* 
  (lambda (cond hook)                              
    (declare (ignore cond hook))
    (format t "Cleaning up ...")
    (ccl:quit)))

После того, как этот код введен в REPL без слизи, отправка SIGINT заставит программу напечатать «Очистка ...» и выйти.

5 голосов
/ 29 мая 2015

Это поздний ответ, но для всех, кто его ищет, посмотрите trivial-signal , доступный на QuicklispЭто основано на CFFI.

Пример

(signal-handler-bind ((:int  (lambda (signo)
                               (declare (ignorable signo))
                               ...handler...)))
  ...body...)
1 голос
/ 24 августа 2015

Если вы используете SBCL, вы не можете изменить маску сигнала, не вызывая сбой SBCL.Спросите nyef о его советах, как исправить SBCL ...

...