SocketStream>>flush question

C. David Shaffer cdshaffer at acm.org
Mon Mar 8 14:56:15 UTC 2004


Yoshiki Ohshima wrote:

>
>  But, you, err, the user of Socket, have to take care of the error
>conditions accordingly.  The low-level code (Socket and SocketStream)
>cannot know what would be the right thing to do on errors because it
>is application specific.
>  
>

That is the case generally but the problem I'm having is that 
SocketStream>>close sends flush so it is the "user" of the Socket.   The 
close should succeed even if the data can't be flushed (in my opinion) 
since it leaves you in a sticky mess if you can't close the socket.  I 
guess that you could expect the caller to protect the close:

[socketStream close] ensure: [socketStream socket isOpen ifTrue: 
[socketStream socket close]]

but this seems a little silly.  I propose a change (below) to 
SocketStream>>close and flush that make them more useful at the 
application level.  Please, if I'm wrong here just let me know...show me 
code to close a SocketStream which ensures that the socket is really closed.

>  There is no guard predicates to ensure the subsequent #sendData: or
>such succeeds as the socket status can be changed after the guard test
>and before #sendData:.  So, the 'fix' to the guard predicate in
>SocketStream>>flush won't 'fix' the whole situation.
>  
>

Yes, you're right about that.  It makes me wonder why there is any 
"guard" at all.  It just makes the SocketStream API more confusing 
(throws an exception _if_ the connection is closed but the close hasn't 
been detected yet).  You've pretty much convinced me that the best 
solution is something like this (in SocketStream):

flush
    "Flush buffered data to socket.  Throws exception if data cannot be 
sent."
    self socket sendData: self outStream contents.
    self resetOutStream

close
    "Attempts to #flush then closes socket.  Exceptions on flush or 
close will be passed up but the close is always attempted."
    [self flush] ensure: [self socket closeAndDestroy: 30]

The usage pattern becomes:

[socketStream close] on: NetworkError do: [:ex | "handle data 
transmission error and/or close error if you like"].

Then the various Socket method would have to be changed to throw the 
various subclasses of NetworkError (filling in gaps where they exist).  
What do you think?

>
>  What I'd do is to handle the ConnectionTimedOut exception and the
>other kind of exception differently if needed.
>  
>
Yes, usually that would be appropriate.  What I'm proposing is having 
"other kind of exception" be subclasses of NetworkError and leave "self 
error: 'primitive failed'" for cases when a primitive fails due to a 
non-sockets I/O related problem.

>  I'm curious what kind of different actions we could take for
>different type of errors.
>  
>
I don't have an answer for that.  At the moment I simply need a 
reasonable way to close a SocketStream which requires better error 
support in Socket.  Maybe these other "actions" will come up as this 
code evolves...?

David

-- 
C. David Shaffer
http://www.cs.westminster.edu/~shaffer
http://www.shaffer-consulting.com





More information about the Squeak-dev mailing list