On Dec 28, 2007 10:53 PM, Stanislaw Halik sthalik@tehran.lain.pl wrote:
On Fri, Dec 28, 2007, Stanislaw Halik wrote:
On Wed, Dec 26, 2007, Erik Huelsmann wrote:
usocket trunk supports a select() like interface to determine which sockets are available for reading. With that code, you could implement the 10 socket readers in 1 thread instead of in 10. The interface returns the sockets which are ready for reading. If the timeout exceeds, an empty list is returned. The interface is called WAIT-FOR-INPUT.
How about wrapping the socket in a gray stream when timeouts are used, and doing WAIT-FOR-INPUT before read operations? That sounds better than changing every place Drakma and Chunga read from sockets.
This can't be done this easily. WAIT-FOR-INPUT interacts badly with buffering. Consider this:
In the LispWorks variant (on Windows) I realised this problem and I've implemented something that takes buffering into account. I'll need to backport that. I think however that this subject is starting to be more about usocket than about Drakma, so, possibly we need to switch this discussion to usocket-devel@ ? I'd gladly work with you (and others) to make WAIT-FOR-INPUT usable.
CL-USER> (usocket:socket-connect "ananke" 25) #<USOCKET:STREAM-USOCKET {B550781}>
CL-USER> (usocket:wait-for-input '#<USOCKET:STREAM-USOCKET {B550781}> :timeout 3) (#<USOCKET:STREAM-USOCKET {B550781}>) 3 CL-USER> (usocket:wait-for-input '#<USOCKET:STREAM-USOCKET {B550781}> :timeout 3) (#<USOCKET:STREAM-USOCKET {B550781}>) 3
CL-USER> (read-char (usocket:socket-stream (car '(#<USOCKET:STREAM-USOCKET {B550781}>)))) #\2
CL-USER> (usocket:wait-for-input '#<USOCKET:STREAM-USOCKET {B550781}> :timeout 3) NIL NIL
The SMTP banner has already been slurped into the buffer and select(2) returns 0. This could work with :buffering :none. usocket doesn't give an option as whether to enable input buffering.
Right. I haven't decided what to do about access to buffering streams (or at least setting the parameter), because in general this can only be an advisory parameter (not all implementations support setting 'bufferedness' of a stream).
As for read timeout support for usocket, only SBCL and LispWorks support it. CLISP has WITH-TIMEOUT, but that would require wrapping the socket in a gray stream with WITH-TIMEOUT. Note that WITH-TIMEOUT in CLISP depends on threads, not enabled by default nor in Debian package.
The UNIX socket FAQ (http://www.developerweb.net/forum/archive/index.php/t-3439.html) suggests that it's nearly impossible to correctly implement timeouts using SO_RCVTIMEO and SO_SENDTIMEO in a portable manner. Too many differences occur on different platforms...
That's why I rather use select()/LISTEN/READ-CHAR/READ-CHAR-NO-HANG/etc. to implement time-out behaviour which can be used on all lisps on all OSes. I hope you don't mind (and that you - as I do - think that the result is what counts).
Thanks for taking the time to test this new usocket behaviour!
bye,
Erik.