Component compat-sbcl

You are here: All Systems / araneida / compat / compat-sbcl

(in-package :araneida)

(defparameter *open-external-format-arguments*
  '(:element-type (unsigned-byte 8) :external-format :iso-8859-1)
)


(eval-when (:load-toplevel :execute)
  (sb-sys:ignore-interrupt SB-UNIX:SIGPIPE)
)


(defun getenv (var)
  (sb-ext:posix-getenv var)
)


(defun forcibly-close-stream (s)
  (let ((fd (sb-sys:fd-stream-fd s)))
    (multiple-value-bind (r e) (ignore-errors (close s) t)
      (unless r
        (format t "Unable to close fd ~A: ~A, trying harder ~%" fd e)
        (multiple-value-bind (r e) (ignore-errors (close s :abort t) t)
          (unless r
            (format t "still unable to close ~A: ~A, try harder ~%" fd e)
            (multiple-value-bind (r e)
                (ignore-errors (sb-unix:unix-close fd) t)
              (unless r
                (format t "Even unix-close failed on ~A:~A, giving up~%"
                        fd e
)
)
)
)
)
)
)
)
)


(defun platform-handle-debugger-condition (condition)
  (typecase condition
    (sb-bsd-sockets::bad-file-descriptor-error
     (format *trace-output*
             "accept: bad file descriptor error (socket shut down?)~%~A~%"
             condition
)
)

    (sb-bsd-sockets::socket-error
     (format *trace-output* "socket error ~A~%" condition)
)

    (sb-ext:timeout
     (format *trace-output* "timed out processing request: ~A~%" condition)
)

    (t
     (format *trace-output* "Caught error: ~A~%" condition)
     (sb-debug:backtrace 15 *trace-output*)
)
)
)


(defun listener-accept-stream (listener)
  (let ((socket (sb-bsd-sockets:socket-accept
                 (http-listener-socket listener)
)
)
)

    (sb-bsd-sockets:socket-make-stream socket :element-type 'character
                                       :external-format :iso-8859-1
                                       :name "socket"
                                       :input t :output t :buffering :full
)
)
)


(eval-when (:compile-toplevel :load-toplevel)
  (defmacro with-file-error-handlers (form handler-message)
    `(handler-case
      ,form
      (sb-int:simple-file-error (c)
       (signal 'http-not-found
        :message ,handler-message
)
)

      (sb-int:simple-stream-error (c)
       (signal 'http-not-found
        :message ,handler-message
)
)
)
)
)


#+sb-thread
(progn
  (defun host-run-thread (id thunk)
    (let ((error-output *error-output*)
          (standard-output *standard-output*)
          (trace-output *trace-output*)
)

      (sb-thread:make-thread (lambda ()        ; rebind the outputs - we need those!
                               (let ((*error-output* error-output)
                                     (*standard-output* standard-output)
                                     (*trace-output* trace-output)
)

                                 (funcall thunk)
)
)

                             :name (format nil "Araneida Server Thread ~A" id)
)
)
)

  
  (defun host-thread-alivep (pid)
    (sb-thread:thread-alive-p pid)
)

  
  (defun host-thread-kill (pid)
    (sb-thread:terminate-thread pid)
)
)


(defun host-close-socket (socket)
  (sb-bsd-sockets:socket-close socket)
)


(eval-when (:compile-toplevel :load-toplevel)
  (defmacro host-with-timeout (timeout &body body)
    `(sb-ext:with-timeout ,timeout
      ,@body
)
)
)


(defun host-make-listener-socket (address port)
  (let ((socket
         (make-instance 'sb-bsd-sockets:inet-socket :type :stream
                        :protocol :tcp
)
)
)

    (setf (sb-bsd-sockets:sockopt-reuse-address socket) t)
    (sb-bsd-sockets:socket-bind socket address port)
    (sb-bsd-sockets:socket-listen socket 15)
    socket
)
)


(defvar *araneida-fd-handlers* nil
  "Our file descriptor handlers for SERVE-EVENT"
)


(defun host-add-fd-handler (listener handler)
  (let ((socket (http-listener-socket listener)))
    (let ((handler-obj (sb-sys:add-fd-handler
                        (sb-bsd-sockets:socket-file-descriptor socket)
                        :input
                        handler
)
)
)

      (push handler-obj *araneida-fd-handlers*)
      handler-obj
)
)
)


(defun host-remove-fd-handler (handler)
  (setq *araneida-fd-handlers*
        (delete handler *araneida-fd-handlers* :test #'eq)
)

  (sb-sys:remove-fd-handler handler)
)


(defmacro host-without-other-handlers (&body body)
  "Run BODY without araneida's handlers therefore ensuring only one
   request is handled at a time. Other handlers are present and may
   be removed/added within BODY."

  (let ((h (gensym)))
  `(let ((,h nil))
    (unwind-protect
         (let ((sb-impl::*descriptor-handlers*
                (remove-if #'(lambda (x)
                               (member x *araneida-fd-handlers*
                                       :test #'eq
)
)

                           sb-impl::*descriptor-handlers*
)
)
)

           (unwind-protect
                (progn
                  ,@body
)

             (setq ,h sb-impl::*descriptor-handlers*)
)
)

      (setq sb-impl::*descriptor-handlers*
            (append ,h *araneida-fd-handlers*)
)
)
)
)
)

Lisppaste pastes can be made by anyone at any time. Imagine a fearsomely comprehensive disclaimer of liability. Now fear, comprehensively.