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?
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.
Thank you.
-pete