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
! !