[iolib-devel] with-open-socket oddness

Stelian Ionescu sionescu at cddr.org
Wed Feb 10 20:17:06 UTC 2010


On Mon, 2010-02-08 at 22:31 -0600, Peter Keller wrote:
> Hello,
> 
> I discovered in my boundary testing of with-open-socket that it sort of has
> a funny behavior I didn't expect.
> 
> Basically, I had a top level code like this in a blocking i/o tcp ipv4
> client talking to a server:
> 
> (with-open-socket
>     (socket :stuff :things)
> 
>   ;; set up i/o handlers, each wrap their reads and writes around
>   ;; handler-case. A disconnector on the sockets removes the io handlers, but
>   ;; doesn't close the socket since with-open-socket should do it.
> 
>   (handler-case
>     ;; run forever until empty (meaning we disconnected from the server),
>     ;; then return.
>     (event-dispatch *base*)
>   
>   (hangup ()
>     (format t "Hangup while writing to server~%"))
> 
>   (end-of-file ()
>     (format t "End of file from server~%"))))
> 
> Now, what happened was, under certain conditions where there is inflight
> data on the sockets, a registered handler could get a signaled condition,
> specifically hangup, that tells me the server went away on a write. This
> is expected. I disconnect the socket which removes the i/o handlers, which
> causes event-dispatch to return since there are no registered handlers....
> and then bam! The with-open-stream performs a (finish-output) and (close) on
> the socket and I get _another_ hangup condition!
> 
> So I had to rewrite the code like this moving the handler-case up one scope:
> 
> (handler-case
>  (with-open-socket
>      (socket :things :stuff)
>    ;; set up i/o handlers, each wrap their reads and writes around
>    ;; handler-case. A disconnector on the sockets removes the io handlers, but
>    ;; doesn't close the socket since with-open-socket should do it.
>    (event-dispatch *base*))
>  
>  (hangup ()
>    (format t "Hangup while writing to server~%"))
> 
>  (end-of-file ()
>    (format t "End of file from server~%"))))
> 
> Is this a to be expected scenario in condition handling with respect to
> with-open-socket? Is this idiomatic code?

This is to be expected. This is what happens: one of the handlers
signals a HANGUP(which is Posix EPIPE), the handler-case handles it and
returns. At his point, since the code wrapped by with-open-socket
returns, w-o-s closes the socket with :abort NIL, which tries again to
flush the output buffer(:abort T would just close the file descriptor),
which causes another HANGUP to be signaled.

> Should the disconnector function close the socket even though with-open-socket
> also closes it? I'm not sure of the right thing to do here.

My opinion is that it's not a good idea to mix with-open-socket and the
event loop because w-o-s is thought for a synchronous data flow. The
only exception to that is if you use w-o-s to open the server socket.
With active sockets, it's better to close them from within the event
loop.

-- 
Stelian Ionescu a.k.a. fe[nl]ix
Quidquid latine dictum sit, altum videtur.
http://common-lisp.net/project/iolib
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part
URL: <https://mailman.common-lisp.net/pipermail/iolib-devel/attachments/20100210/b3367084/attachment.sig>


More information about the iolib-devel mailing list