A long time ago (Dec 2007) there was a patch [1] for drakma to implement
timeouts with sbcl. It was rejected with suggestion to post similar
patch into usocket library.

Totday, I start to learn lisp programing and I need http-request for my
small program. I took drakma for this. But it does not support timeouts on
sbcl. I use debian and it seems sbcl - is the best choice for me.

By googling I found a patch for drakma. I repplaied it for 1.2.3 drakma. It
seems to me, it still forth appling into main line of drakma. I did not
investigate 
what happen with usocket patch and such long time shows - this patch needs 
to be applied anyway :-)

1. http://common-lisp.net/pipermail/drakma-devel/2007-December/000601.html

--
Alexander Litvinov


commit 734c82f851296f8eb057f519fb78d4c667f99436
Author: Alexander Litvinov <l...@academsoft.ru>
Date:   Fri Mar 25 07:58:05 2011 +0600

    Support for connection-timeout on SBCL.
    
    I've updated the patch to support the IO-TIMEOUT keyword argument. It's
    not possible to non-intrusively support read- and write-timeouts
    separately to bring the API in congruency with LispWorks.
    
    The resolver error gets changed to SIMPLE-ERROR because it's not an
    ERROR, but a CONDITION (signalled with ERROR, though).
    
    I've stress-tested the patch, running 30 threads doing HTTP-REQUEST.
    
    My rationale for including the patch - it doesn't change the program
    logic much, and except for the function definition and socket connection
    there's no special-casing for SBCL.
    
    The timeout option is crucial for me: my typical usage is running
    concurrent threads accessing URLs posted in spam to make the senders
    think I'm a used accessing the page, in turn sending more spam,
    addresses of which land in my spamtrap. Some of the URLs point to broken
    httpds, leaving an open connection without sending any replies. This
    leads to unfinished requests using threads and hanging for days.
    
    If you feel like maintaing a piece of code for SBCL, by all means please
    do so. I think other SBCL users might benefit from it.
    
    URL: http://common-lisp.net/pipermail/drakma-devel/2007-December/000601.html
    Author: Stanislaw Halik <sthalik at tehran.lain.pl>

diff --git a/request.lisp b/request.lisp
index 2715c26..5575bb8 100644
--- a/request.lisp
+++ b/request.lisp
@@ -29,6 +29,37 @@
 
 (in-package :drakma)
 
+#+sbcl
+(require '#:sb-bsd-sockets)
+#+:sbcl
+(defun sbcl-connect-with-timeout (host port connection-timeout io-timeout &key (element-type 'character))
+  (let* ((sock (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp))
+         (octet-addr
+          (handler-case
+              (sb-bsd-sockets:host-ent-address (sb-bsd-sockets:get-host-by-name host))
+            (sb-bsd-sockets:host-not-found-error (e)
+              (error "Can't resolve ~a: ~a" host e))))
+         (fd (sb-bsd-sockets:socket-file-descriptor sock)))
+    (setf (sb-bsd-sockets:non-blocking-mode sock) t)
+    (handler-case
+        (sb-bsd-sockets:socket-connect sock octet-addr port)
+      (sb-bsd-sockets:socket-error (c)
+        (unless (= (sb-bsd-sockets::socket-error-errno c) sb-posix:einprogress)
+          (error c))))
+    (setf (sb-bsd-sockets:non-blocking-mode sock) nil)
+    (loop
+         (if (sb-sys:wait-until-fd-usable fd :output connection-timeout)
+             (return)
+             (unless (= sb-posix::eintr (sb-alien:get-errno))
+               (sb-bsd-sockets:socket-error "open"))))
+    (sb-bsd-sockets::socket-make-stream
+     sock
+     :input t
+     :output t
+     :timeout io-timeout
+     :buffering :full
+     :element-type element-type)))
+
 (defun determine-body-format (headers external-format-in)
   "The default function used by Drakma to determine how the content
 body is to be read.  See the docstring of *BODY-FORMAT-FUNCTION* for
@@ -200,8 +231,9 @@ headers of the chunked stream \(if any) as a second value."
                               force-binary
                               want-stream
                               stream
-                              #+:lispworks (connection-timeout 20)
+                              #+(or :lispworks :sbcl) (connection-timeout 20)
                               #+:lispworks (read-timeout 20)
+                              #+:sbcl (io-timeout 20)
                               #+(and :lispworks (not :lw-does-not-have-write-timeout))
                               (write-timeout 20 write-timeout-provided-p)
                               #+:openmcl
@@ -459,7 +491,10 @@ only available on CCL 1.2 and later."
                                                           #-:lw-does-not-have-write-timeout
                                                           write-timeout
                                                           :errorp t)
-                                    #-:lispworks
+                                    #+:sbcl
+                                    (sbcl-connect-with-timeout host port connection-timeout io-timeout
+                                                               :element-type '(unsigned-byte 8))
+                                    #-(or :lispworks sbcl)
                                     (usocket:socket-stream
                                      (usocket:socket-connect host port
                                                              :element-type 'octet
_______________________________________________
drakma-devel mailing list
drakma-devel@common-lisp.net
http://common-lisp.net/cgi-bin/mailman/listinfo/drakma-devel

Reply via email to