From: Todd S. <ts...@op...> - 2005-05-20 15:16:04
|
David Tolpin <dv...@da...> writes: > On 20.05.2005, at 15:20, Bruno Haible wrote: > >> No. David pointed out that two things are wrong in the current >> implementation: >> - (CLOSE socket) causes loss of data. >> - Users need to know about the SOCKET-SERVER-SHUTDOWN function. >> We should fix both simultaneously, by having CLOSE call shutdown(). > > There is a discrepancy in semantics. According to modern Linux > understanding of RFCs, widely cited and quoted in the kernel, when a > socket is closed and has data pending, RST should be sent > immediately. That means that if a program reads from client and > sends back response and close, and the read wasn't complete (just > because it terminated), the client will not be able to read the > response because it will get ENOTCONN error instead (due to RST). Ignoring the "There is a discrepancy in semantics.", this is mostly correct. (I think you get a different error.) > There is a rationale behind this, but the result is that a socket > must be explicitly shut down before closing on Linux. This is false, and indicates that you probably don't understand the rationale for sending the RST. The way I understand it, briefly, is that TCP is supposed to guarantee reliable data delivery to applications. If one end doesn't read all of the data that the other end sent, the sending end needs to be notified of that, and that is why the RST is sent. Trying to subvert that by doing a shutdown before a close is a bad idea. Looking at it another way, the client and server are supposed to be talking some protocol. If the client sends more data than the server knows how to handle, there's a protocol violation. You shouldn't sweep that under the covers. Either the client can be fixed to send only what the server can handle, or the server can be modified to accept extra junk from the client (by explicitly reading it from the socket and throwing it away). Modifying clisp's socket streams to do this type of thing automatically is, again, a bad idea. (Note that there may already be some risk of this if you're using buffered streams, but there doesn't seem to be an easy way out for that.) There is certainly no general requirement to perform a shutdown() before a close() on linux. With correct clients and servers, shutdown is usually not needed. > If CLISP is > committed to provide access to the Unix semantics, shutdown should > shut down and close should close, at least in some of their > invocations. I agree with this. clisp's shutdown should not close the stream, nor should stream close perform a shutdown, in the normal case. If the application wants that, it can do it itself. > I'd propose to keep socket-stream-shutdown but remove call to > builtin_stream_close from there, and respect :ABORT in close, calling > shutdown if :ABORT is nil. This way, the default mode of operation > would be to allow users to write programs which behave as expected, > and when the user needs to write a server with abrupt close, she calls > (close socket :abort t) letting the server send RST if there is still > data. Calling shutdown in the (close socket :abort nil) case is wrong, I think. It might be needed in the :abort t case. -- Todd Sabin <ts...@op...> |