[Openmcl-devel] Who uses CL+SSL and CCL?
gb at clozure.com
Fri Jan 16 19:46:19 UTC 2009
On Fri, 16 Jan 2009, John McAleely wrote:
> I could well imagine other implementations where this hasn't been
> exposed as a problem. Is it possible that a recent change in CCL has
> surfaced this bug in the CL+SSL test code?
I have more difficulty imagining that. I don't know of any CCL
change that would have affected whether or not this really worked.
I also don't know the details of other implementations's stream/socket
implementations, but if it is true that (and I'll try to use
upper-case CLOSE to mean "calling CL:CLOSE on a stream object" and
lower-case close to mean "the abstract act of closing some lower-level
resource, such as a file descriptor, by whatever means are appropriate")
a) closing (via CL:CLOSE) a stream that's associated with a file
descriptor closes (invalidates, tells the OS to remove I/O resources
associated with) the file descriptor
b) closing (without :ABORT) an output stream that has unwritten,
buffered data tries to ensure that that data is written to the
underlying object that the stream encapsulates (an fd, an SSL
handle associated with an fd, whatever ...), via FORCE-OUTPUT
or some similar mechanism.
1) if two streams share the same fd, calling CLOSE on one of them
will close that fd, making further I/O on the other stream impossible.
2) in that scenario, if the second stream has buffered output data,
CLOSE-ing it (and trying to do I/O involving the closed fd) will fail.
(There'd basically be no way to ensure that bufferd data is written to
the fd, because the OS has been told that the fd is invalid. In the
example code, the stream encapsulates an SSL handle that's associated
with a closed fd.)
3) if there wasn't any buffered output when the second stream was
closed - and if the second stream simply encapsulated an FD and SSL
wasn't involved, to make this discussion simpler - then CLOSE-ing
the second stream would attempt to close an already-closed fd. That's
an error, but CCL silently ignores it. If an implementation chose
to signal an error in that case, I think that it'd be justified in
doing so. (So just the act of closing two streams that use the
same fd - whether there's any buffered output involved or not -
involves an anomalous situation that may or may not be detected
Neither of the assumptions (a) or (b) above seem particularly
unreasonable, though I don't know enough about other lisps'
stream implementations to be able to claim that they're universally
true. I would be willing to "strongly guess" that they're largely
if not entirely true in many lisp implementations (but reserve
the right to wimp out, out of ignorance.) If the assumptions are
correct, then I imagine that the example - as written - would or
could fail in many implementations.
> I'm happy that making this change is an appropriate way to fix this
You might want to talk to the author of the package about what
they think the best solution would be, but at the moment I'd
vote for changing the order of the CLOSE calls (and not adding
an explicit FORCE-OUTPUT as I'd suggested yesterday.) The
CLOSE method on SSL-STREAMs does:
(when (streamp (ssl-stream-socket stream))
(close (ssl-stream-socket stream)))
In the example, the SSL stream's SSL-STREAM-SOCKET is just an fd (a
small integer), so CLOSE isn't called (though FORCE-OUTPUT may have
been called just before reaching this point). The fd would still be
open when the stream bound to "socket" is CLOSEd; if there were
unbuffered output on the "socket" stream - perhaps unlikely - it
could be flushed, etc.
More information about the Openmcl-devel