On Sun, 5 Mar 2000 13:54:45 "Lex Spoon" <[EMAIL PROTECTED]> wrote:
>Actually, I've seen this on minnow, which (I think) is a 300-400MHz G3
> If you save a large page, then the socket seems to get closed before
>all the data comes back.  The page actually does get saved, but the
>client doesn't get to see it.  That's why saving it a second time would
>generate an edit conflict.
>
>This problem would be worse on faster servers, because they can close
>the socket faster :)
>
>Overall,  closeAndDestroy: is supposed to avoid this problem.  I
>remember at one time that the delay was turned way down in
>closeAndDestroy: in Comanche.  Is that currently the case in
>Comanche/ComSwiki?

This may be related to the problem observed last year when saves in quick succession 
seemed to hang some servers. It may be that the timeout was reduced so that the socket 
would likely be destroyed before the second save arrived, thus avoiding he hang. 
Unfortunately, this could prematurely terminate the data being sent (actually, that 
could happen with any timeout value since a slow/noisy network could legitimately take 
a long time send all the data). If the timeout was reduced to fix the hang, it might 
be better to fix the hang and restore the timeout to a healthier value. Enclosed is a 
changeset that seemed to fix the problem.

Cheers,
Bob

'From Squeak2.8alpha of 13 January 2000 [latest update: #1873] on 5 March 2000 at 
4:04:54 pm'!
"Change Set:            socketClose
Date:                   5 March 2000
Author:                 Bob Arning

There can be a problem trying to close a socket while there is still unread data 
available. On the Mac, the close may need to timeout and a second request during that 
time may hang the machine altogether. How this affects other OS is unclear. As to why 
dataAvailable is an issue:

1. Squeak actually has code that *almost* gets it right.
        Socket>>closeAndDestroy: sends self waitForDisconnectionUntil: ...
        Socket>>waitForDisconnectionUntil: tries to read any data that comes in after 
the close using self discardReceivedData.
        Socket>>discardReceivedData will _only_ read the data if the socket is 
Connected, but by this time the socket is ThisEndClosed and the data is ignored.

I made a change so that Socket>>discardReceivedData reads data in either Connected or 
ThisEndClosed status and was able to continuously edit/save/etc. This would appear to 
be a more robust approach than the one I previously suggested, but if you adopt this 
approach, you will probably want to deal with the self inform: in 
Socket>>waitForDisconnectionUntil: in a less intrusive manner.

2. It is curious why saving short pages seems to leave no unread data, but saving long 
pages leaves a CRLF unread. Who decides when to stop reading data from the socket? And 
how?

3. For the terminally curious, here is an excerpt from the MacTCP docs that explains 
the close a bit more fully than I had previously understood:
=============================
Connection closing
TCP closes communications gracefully. All outstanding Send requests are transmitted 
and acknowledged before the connection is allowed to close. You can issue several 
TCPSend commands followed by a TCPClose command and expect that all the data will be 
sent successfully to the remote TCP. 
A TCPClose command means �I have no more data to send,� but it does not mean �I will 
receive no more data� or �shut down this connection immediately.� A connection may 
remain open indefinitely as the remote TCP continues to send data after a TCPClose 
command has been completed. When the remote TCP also issues a close command�and only 
then�the connection is closed. A TCPRcv command should be issued after a TCPClose 
command has been completed to make sure that all the data is received.
If the desired effect is to break the connection without any assurance that all data 
in transit is delivered, use the TCPAbort command.

==================
"!


!Socket methodsFor: 'queries' stamp: 'RAA 3/5/2000 16:03'!
isConnectedOrThisEndClosed
        | status |
        "Return true if this socket is connected OR has been closed at this end only."

        socketHandle == nil ifTrue: [^ false].
        status _ self primSocketConnectionStatus: socketHandle.
        ^status == Connected or: [status == ThisEndClosed]
! !

!Socket methodsFor: 'sending-receiving' stamp: 'RAA 10/21/1999 10:58'!
discardReceivedData
        "Discard any data received up until now, and return the number of bytes 
discarded."

        | buf totalBytesDiscarded |
        buf _ String new: 10000.
        totalBytesDiscarded _ 0.
        [self isConnectedOrThisEndClosed and: [self dataAvailable]] whileTrue: [
                totalBytesDiscarded _
                        totalBytesDiscarded + (self receiveDataInto: buf)].
        ^ totalBytesDiscarded
! !

Reply via email to